diff mbox series

[net-next,v6,2/4] ethtool: provide customized dim profile management

Message ID 1712844751-53514-3-git-send-email-hengqi@linux.alibaba.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series ethtool: provide the dim profile fine-tuning channel | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; GEN HAS DIFF 2 files changed, 250 insertions(+);
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 3505 this patch: 3714
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 4 maintainers not CCed: linux-doc@vger.kernel.org corbet@lwn.net andrew@lunn.ch ahmed.zaki@intel.com
netdev/build_clang fail Errors and warnings before: 110 this patch: 106
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 3959 this patch: 3961
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 84 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns WARNING: line length of 94 exceeds 80 columns WARNING: line length of 96 exceeds 80 columns WARNING: line length of 97 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc fail Errors and warnings before: 106 this patch: 114
netdev/source_inline fail Was 0 now: 1

Commit Message

Heng Qi April 11, 2024, 2:12 p.m. UTC
The NetDIM library, currently leveraged by an array of NICs, delivers
excellent acceleration benefits. Nevertheless, NICs vary significantly
in their dim profile list prerequisites.

Specifically, virtio-net backends may present diverse sw or hw device
implementation, making a one-size-fits-all parameter list impractical.
On Alibaba Cloud, the virtio DPU's performance under the default DIM
profile falls short of expectations, partly due to a mismatch in
parameter configuration.

I also noticed that ice/idpf/ena and other NICs have customized
profilelist or placed some restrictions on dim capabilities.

Motivated by this, I tried adding new params for "ethtool -C" that provides
a per-device control to modify and access a device's interrupt parameters.

Usage
========
1. Query the currently customized list of the device

$ ethtool -c ethx
...
rx-eqe-profile:
{.usec =   1, .pkts = 256, .comps =   0,},
{.usec =   8, .pkts = 256, .comps =   0,},
{.usec =  64, .pkts = 256, .comps =   0,},
{.usec = 128, .pkts = 256, .comps =   0,},
{.usec = 256, .pkts = 256, .comps =   0,}
rx-cqe-profile:   n/a
tx-eqe-profile:   n/a
tx-cqe-profile:   n/a

2. Tune
$ ethtool -C ethx rx-eqe-profile 1,1,0_2,2,0_3,3,0_4,4,0_5,5,0
$ ethtool -c ethx
...
rx-eqe-profile:
{.usec =   1, .pkts =   1, .comps =   0,},
{.usec =   2, .pkts =   2, .comps =   0,},
{.usec =   3, .pkts =   3, .comps =   0,},
{.usec =   4, .pkts =   4, .comps =   0,},
{.usec =   5, .pkts =   5, .comps =   0,}
rx-cqe-profile:   n/a
tx-eqe-profile:   n/a
tx-cqe-profile:   n/a

3. Hint
If the device does not support some type of customized dim
profiles, the corresponding "n/a" will display.

Signed-off-by: Heng Qi <hengqi@linux.alibaba.com>
---
 Documentation/netlink/specs/ethtool.yaml     |  33 +++++
 Documentation/networking/ethtool-netlink.rst |   8 ++
 include/linux/ethtool.h                      |  12 +-
 include/linux/netdevice.h                    |  15 +++
 include/uapi/linux/ethtool_netlink.h         |  24 ++++
 net/core/dev.c                               |  63 +++++++++
 net/ethtool/coalesce.c                       | 184 ++++++++++++++++++++++++++-
 7 files changed, 336 insertions(+), 3 deletions(-)

Comments

Brett Creeley April 11, 2024, 3:19 p.m. UTC | #1
On 4/11/2024 7:12 AM, Heng Qi wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> The NetDIM library, currently leveraged by an array of NICs, delivers
> excellent acceleration benefits. Nevertheless, NICs vary significantly
> in their dim profile list prerequisites.
> 
> Specifically, virtio-net backends may present diverse sw or hw device
> implementation, making a one-size-fits-all parameter list impractical.
> On Alibaba Cloud, the virtio DPU's performance under the default DIM
> profile falls short of expectations, partly due to a mismatch in
> parameter configuration.
> 
> I also noticed that ice/idpf/ena and other NICs have customized
> profilelist or placed some restrictions on dim capabilities.
> 
> Motivated by this, I tried adding new params for "ethtool -C" that provides
> a per-device control to modify and access a device's interrupt parameters.
> 
> Usage
> ========
> 1. Query the currently customized list of the device
> 
> $ ethtool -c ethx
> ...
> rx-eqe-profile:
> {.usec =   1, .pkts = 256, .comps =   0,},
> {.usec =   8, .pkts = 256, .comps =   0,},
> {.usec =  64, .pkts = 256, .comps =   0,},
> {.usec = 128, .pkts = 256, .comps =   0,},
> {.usec = 256, .pkts = 256, .comps =   0,}
> rx-cqe-profile:   n/a
> tx-eqe-profile:   n/a
> tx-cqe-profile:   n/a
> 
> 2. Tune
> $ ethtool -C ethx rx-eqe-profile 1,1,0_2,2,0_3,3,0_4,4,0_5,5,0
> $ ethtool -c ethx
> ...
> rx-eqe-profile:
> {.usec =   1, .pkts =   1, .comps =   0,},
> {.usec =   2, .pkts =   2, .comps =   0,},
> {.usec =   3, .pkts =   3, .comps =   0,},
> {.usec =   4, .pkts =   4, .comps =   0,},
> {.usec =   5, .pkts =   5, .comps =   0,}
> rx-cqe-profile:   n/a
> tx-eqe-profile:   n/a
> tx-cqe-profile:   n/a
> 
> 3. Hint
> If the device does not support some type of customized dim
> profiles, the corresponding "n/a" will display.

What if the user specifies a *-eqe-profile and *-cqe-profile for rx 
and/or tx? Is that supported? If so, which one is the active profile?

Maybe I missed this, but it doesn't seem like the output from "ethtool 
-c ethX" shows the active profile it just dumps the profile configurations.

Thanks,

Brett

[snip]
Heng Qi April 12, 2024, 2:07 a.m. UTC | #2
在 2024/4/11 下午11:19, Brett Creeley 写道:
>
>
> On 4/11/2024 7:12 AM, Heng Qi wrote:
>> Caution: This message originated from an External Source. Use proper 
>> caution when opening attachments, clicking links, or responding.
>>
>>
>> The NetDIM library, currently leveraged by an array of NICs, delivers
>> excellent acceleration benefits. Nevertheless, NICs vary significantly
>> in their dim profile list prerequisites.
>>
>> Specifically, virtio-net backends may present diverse sw or hw device
>> implementation, making a one-size-fits-all parameter list impractical.
>> On Alibaba Cloud, the virtio DPU's performance under the default DIM
>> profile falls short of expectations, partly due to a mismatch in
>> parameter configuration.
>>
>> I also noticed that ice/idpf/ena and other NICs have customized
>> profilelist or placed some restrictions on dim capabilities.
>>
>> Motivated by this, I tried adding new params for "ethtool -C" that 
>> provides
>> a per-device control to modify and access a device's interrupt 
>> parameters.
>>
>> Usage
>> ========
>> 1. Query the currently customized list of the device
>>
>> $ ethtool -c ethx
>> ...
>> rx-eqe-profile:
>> {.usec =   1, .pkts = 256, .comps =   0,},
>> {.usec =   8, .pkts = 256, .comps =   0,},
>> {.usec =  64, .pkts = 256, .comps =   0,},
>> {.usec = 128, .pkts = 256, .comps =   0,},
>> {.usec = 256, .pkts = 256, .comps =   0,}
>> rx-cqe-profile:   n/a
>> tx-eqe-profile:   n/a
>> tx-cqe-profile:   n/a
>>
>> 2. Tune
>> $ ethtool -C ethx rx-eqe-profile 1,1,0_2,2,0_3,3,0_4,4,0_5,5,0
>> $ ethtool -c ethx
>> ...
>> rx-eqe-profile:
>> {.usec =   1, .pkts =   1, .comps =   0,},
>> {.usec =   2, .pkts =   2, .comps =   0,},
>> {.usec =   3, .pkts =   3, .comps =   0,},
>> {.usec =   4, .pkts =   4, .comps =   0,},
>> {.usec =   5, .pkts =   5, .comps =   0,}
>> rx-cqe-profile:   n/a
>> tx-eqe-profile:   n/a
>> tx-cqe-profile:   n/a
>>
>> 3. Hint
>> If the device does not support some type of customized dim
>> profiles, the corresponding "n/a" will display.
>
> What if the user specifies a *-eqe-profile and *-cqe-profile for rx 
> and/or tx? Is that supported? If so, which one is the active profile?


I think you mean GET? GET currently does not support any parameters, the 
working profile will be displayed.

>
> Maybe I missed this, but it doesn't seem like the output from "ethtool 
> -c ethX" shows the active profile it just dumps the profile 
> configurations.

Now it is required that dev->priv_flags is set to one of 
IFF_PROFILE_{USEC, PKTS, COMPS} (which means that the
driver supports configurable profiles) before the profile can be queried 
or do you want to query without this restriction?

Thanks!

>
> Thanks,
>
> Brett
>
> [snip]
kernel test robot April 12, 2024, 3:56 a.m. UTC | #3
Hi Heng,

kernel test robot noticed the following build warnings:

[auto build test WARNING on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heng-Qi/linux-dim-move-useful-macros-to-h-file/20240411-221400
base:   net-next/main
patch link:    https://lore.kernel.org/r/1712844751-53514-3-git-send-email-hengqi%40linux.alibaba.com
patch subject: [PATCH net-next v6 2/4] ethtool: provide customized dim profile management
config: riscv-defconfig (https://download.01.org/0day-ci/archive/20240412/202404121112.lymscQm1-lkp@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 8b3b4a92adee40483c27f26c478a384cd69c6f05)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240412/202404121112.lymscQm1-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404121112.lymscQm1-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> net/ethtool/coalesce.c:373: warning: Function parameter or struct member 'dev' not described in 'ethnl_update_profile'
>> net/ethtool/coalesce.c:373: warning: Excess function parameter 'mod' description in 'ethnl_update_profile'


vim +373 net/ethtool/coalesce.c

   347	
   348	/**
   349	 * ethnl_update_profile - get a nla nest with four child nla nests from userspace.
   350	 * @dst: data get from the driver and modified by ethnl_update_profile.
   351	 * @nests: nest attr ETHTOOL_A_COALESCE_*X_*QE_PROFILE to set driver's profile.
   352	 * @mod: whether the data is modified
   353	 * @extack: Netlink extended ack
   354	 *
   355	 * Layout of nests:
   356	 *   Nested ETHTOOL_A_COALESCE_*X_*QE_PROFILE attr
   357	 *     Nested ETHTOOL_A_MODERATIONS_MODERATION attr
   358	 *       ETHTOOL_A_MODERATION_USEC attr
   359	 *       ETHTOOL_A_MODERATION_PKTS attr
   360	 *       ETHTOOL_A_MODERATION_COMPS attr
   361	 *     ...
   362	 *     Nested ETHTOOL_A_MODERATIONS_MODERATION attr
   363	 *       ETHTOOL_A_MODERATION_USEC attr
   364	 *       ETHTOOL_A_MODERATION_PKTS attr
   365	 *       ETHTOOL_A_MODERATION_COMPS attr
   366	 *
   367	 * Returns 0 on success or a negative error code.
   368	 */
   369	static inline int ethnl_update_profile(struct net_device *dev,
   370					       struct dim_cq_moder *dst,
   371					       const struct nlattr *nests,
   372					       struct netlink_ext_ack *extack)
 > 373	{
   374		struct nlattr *tb_moder[ARRAY_SIZE(coalesce_set_profile_policy)];
   375		struct dim_cq_moder profile[NET_DIM_PARAMS_NUM_PROFILES];
   376		struct nlattr *nest;
   377		int ret, rem, i = 0;
   378	
   379		if (!nests)
   380			return 0;
   381	
   382		if (!dst)
   383			return -EOPNOTSUPP;
   384	
   385		nla_for_each_nested_type(nest, ETHTOOL_A_MODERATIONS_MODERATION, nests, rem) {
   386			ret = nla_parse_nested(tb_moder,
   387					       ARRAY_SIZE(coalesce_set_profile_policy) - 1,
   388					       nest, coalesce_set_profile_policy,
   389					       extack);
   390			if (ret)
   391				return ret;
   392	
   393			if (NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_USEC) ||
   394			    NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_PKTS) ||
   395			    NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_COMPS))
   396				return -EINVAL;
   397	
   398			profile[i].usec = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_USEC]);
   399			profile[i].pkts = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_PKTS]);
   400			profile[i].comps = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_COMPS]);
   401	
   402			if ((dst[i].usec != profile[i].usec && !(dev->priv_flags & IFF_PROFILE_USEC)) ||
   403			    (dst[i].pkts != profile[i].pkts && !(dev->priv_flags & IFF_PROFILE_PKTS)) ||
   404			    (dst[i].comps != profile[i].comps && !(dev->priv_flags & IFF_PROFILE_COMPS)))
   405				return -EOPNOTSUPP;
   406	
   407			i++;
   408		}
   409	
   410		memcpy(dst, profile, sizeof(profile));
   411	
   412		return 0;
   413	}
   414
kernel test robot April 12, 2024, 4:39 a.m. UTC | #4
Hi Heng,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heng-Qi/linux-dim-move-useful-macros-to-h-file/20240411-221400
base:   net-next/main
patch link:    https://lore.kernel.org/r/1712844751-53514-3-git-send-email-hengqi%40linux.alibaba.com
patch subject: [PATCH net-next v6 2/4] ethtool: provide customized dim profile management
config: um-allnoconfig (https://download.01.org/0day-ci/archive/20240412/202404121200.pplgT1xP-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240412/202404121200.pplgT1xP-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404121200.pplgT1xP-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from net/core/dev.c:80:
   In file included from include/linux/sched/isolation.h:7:
   In file included from include/linux/tick.h:8:
   In file included from include/linux/clockchips.h:14:
   In file included from include/linux/clocksource.h:22:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     547 |         val = __raw_readb(PCI_IOBASE + addr);
         |                           ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     560 |         val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
         |                                                         ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
      37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
         |                                                   ^
   In file included from net/core/dev.c:80:
   In file included from include/linux/sched/isolation.h:7:
   In file included from include/linux/tick.h:8:
   In file included from include/linux/clockchips.h:14:
   In file included from include/linux/clocksource.h:22:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     573 |         val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
         |                                                         ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
      35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
         |                                                   ^
   In file included from net/core/dev.c:80:
   In file included from include/linux/sched/isolation.h:7:
   In file included from include/linux/tick.h:8:
   In file included from include/linux/clockchips.h:14:
   In file included from include/linux/clocksource.h:22:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     584 |         __raw_writeb(value, PCI_IOBASE + addr);
         |                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     594 |         __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
         |                                                       ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     604 |         __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
         |                                                       ~~~~~~~~~~ ^
   include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     692 |         readsb(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     700 |         readsw(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     708 |         readsl(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     717 |         writesb(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
   include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     726 |         writesw(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
   include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     735 |         writesl(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
>> net/core/dev.c:10235:58: error: no member named 'rx_eqe_profile' in 'struct net_device'
    10235 |         int length = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*dev->rx_eqe_profile);
          |                                                            ~~~  ^
   net/core/dev.c:10242:8: error: no member named 'rx_eqe_profile' in 'struct net_device'
    10242 |                 dev->rx_eqe_profile = kzalloc(length, GFP_KERNEL);
          |                 ~~~  ^
   net/core/dev.c:10243:13: error: no member named 'rx_eqe_profile' in 'struct net_device'
    10243 |                 if (!dev->rx_eqe_profile)
          |                      ~~~  ^
   net/core/dev.c:10245:15: error: no member named 'rx_eqe_profile' in 'struct net_device'
    10245 |                 memcpy(dev->rx_eqe_profile, rx_profile[0], length);
          |                        ~~~  ^
>> net/core/dev.c:10248:8: error: no member named 'rx_cqe_profile' in 'struct net_device'
    10248 |                 dev->rx_cqe_profile = kzalloc(length, GFP_KERNEL);
          |                 ~~~  ^
   net/core/dev.c:10249:13: error: no member named 'rx_cqe_profile' in 'struct net_device'
    10249 |                 if (!dev->rx_cqe_profile)
          |                      ~~~  ^
   net/core/dev.c:10251:15: error: no member named 'rx_cqe_profile' in 'struct net_device'
    10251 |                 memcpy(dev->rx_cqe_profile, rx_profile[1], length);
          |                        ~~~  ^
>> net/core/dev.c:10254:8: error: no member named 'tx_eqe_profile' in 'struct net_device'
    10254 |                 dev->tx_eqe_profile = kzalloc(length, GFP_KERNEL);
          |                 ~~~  ^
   net/core/dev.c:10255:13: error: no member named 'tx_eqe_profile' in 'struct net_device'
    10255 |                 if (!dev->tx_eqe_profile)
          |                      ~~~  ^
   net/core/dev.c:10257:15: error: no member named 'tx_eqe_profile' in 'struct net_device'
    10257 |                 memcpy(dev->tx_eqe_profile, tx_profile[0], length);
          |                        ~~~  ^
>> net/core/dev.c:10260:8: error: no member named 'tx_cqe_profile' in 'struct net_device'
    10260 |                 dev->tx_cqe_profile = kzalloc(length, GFP_KERNEL);
          |                 ~~~  ^
   net/core/dev.c:10261:13: error: no member named 'tx_cqe_profile' in 'struct net_device'
    10261 |                 if (!dev->tx_cqe_profile)
          |                      ~~~  ^
   net/core/dev.c:10263:15: error: no member named 'tx_cqe_profile' in 'struct net_device'
    10263 |                 memcpy(dev->tx_cqe_profile, tx_profile[1], length);
          |                        ~~~  ^
   net/core/dev.c:11063:14: error: no member named 'rx_eqe_profile' in 'struct net_device'
    11063 |                 kfree(dev->rx_eqe_profile);
          |                       ~~~  ^
   net/core/dev.c:11066:14: error: no member named 'rx_cqe_profile' in 'struct net_device'
    11066 |                 kfree(dev->rx_cqe_profile);
          |                       ~~~  ^
   net/core/dev.c:11069:14: error: no member named 'tx_eqe_profile' in 'struct net_device'
    11069 |                 kfree(dev->tx_eqe_profile);
          |                       ~~~  ^
   net/core/dev.c:11072:14: error: no member named 'tx_cqe_profile' in 'struct net_device'
    11072 |                 kfree(dev->tx_cqe_profile);
          |                       ~~~  ^
   12 warnings and 17 errors generated.
--
   In file included from net/ethtool/coalesce.c:3:
   In file included from net/ethtool/netlink.h:6:
   In file included from include/linux/ethtool_netlink.h:6:
   In file included from include/uapi/linux/ethtool_netlink.h:12:
   In file included from include/linux/ethtool.h:18:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/um/include/asm/hardirq.h:5:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     547 |         val = __raw_readb(PCI_IOBASE + addr);
         |                           ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     560 |         val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
         |                                                         ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
      37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
         |                                                   ^
   In file included from net/ethtool/coalesce.c:3:
   In file included from net/ethtool/netlink.h:6:
   In file included from include/linux/ethtool_netlink.h:6:
   In file included from include/uapi/linux/ethtool_netlink.h:12:
   In file included from include/linux/ethtool.h:18:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/um/include/asm/hardirq.h:5:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     573 |         val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
         |                                                         ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
      35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
         |                                                   ^
   In file included from net/ethtool/coalesce.c:3:
   In file included from net/ethtool/netlink.h:6:
   In file included from include/linux/ethtool_netlink.h:6:
   In file included from include/uapi/linux/ethtool_netlink.h:12:
   In file included from include/linux/ethtool.h:18:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/um/include/asm/hardirq.h:5:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     584 |         __raw_writeb(value, PCI_IOBASE + addr);
         |                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     594 |         __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
         |                                                       ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     604 |         __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
         |                                                       ~~~~~~~~~~ ^
   include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     692 |         readsb(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     700 |         readsw(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     708 |         readsl(PCI_IOBASE + addr, buffer, count);
         |                ~~~~~~~~~~ ^
   include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     717 |         writesb(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
   include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     726 |         writesw(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
   include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
     735 |         writesl(PCI_IOBASE + addr, buffer, count);
         |                 ~~~~~~~~~~ ^
>> net/ethtool/coalesce.c:268:11: error: no member named 'rx_eqe_profile' in 'struct net_device'
     268 |                                  dev->rx_eqe_profile, supported) ||
         |                                  ~~~  ^
>> net/ethtool/coalesce.c:270:11: error: no member named 'rx_cqe_profile' in 'struct net_device'
     270 |                                  dev->rx_cqe_profile, supported) ||
         |                                  ~~~  ^
>> net/ethtool/coalesce.c:272:11: error: no member named 'tx_eqe_profile' in 'struct net_device'
     272 |                                  dev->tx_eqe_profile, supported) ||
         |                                  ~~~  ^
>> net/ethtool/coalesce.c:274:11: error: no member named 'tx_cqe_profile' in 'struct net_device'
     274 |                                  dev->tx_cqe_profile, supported))
         |                                  ~~~  ^
   net/ethtool/coalesce.c:479:39: error: no member named 'rx_eqe_profile' in 'struct net_device'
     479 |         ret = ethnl_update_profile(dev, dev->rx_eqe_profile,
         |                                         ~~~  ^
   net/ethtool/coalesce.c:484:39: error: no member named 'rx_cqe_profile' in 'struct net_device'
     484 |         ret = ethnl_update_profile(dev, dev->rx_cqe_profile,
         |                                         ~~~  ^
   net/ethtool/coalesce.c:489:39: error: no member named 'tx_eqe_profile' in 'struct net_device'
     489 |         ret = ethnl_update_profile(dev, dev->tx_eqe_profile,
         |                                         ~~~  ^
   net/ethtool/coalesce.c:494:39: error: no member named 'tx_cqe_profile' in 'struct net_device'
     494 |         ret = ethnl_update_profile(dev, dev->tx_cqe_profile,
         |                                         ~~~  ^
   12 warnings and 8 errors generated.


vim +10235 net/core/dev.c

 10232	
 10233	static int dev_dim_profile_init(struct net_device *dev)
 10234	{
 10235		int length = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*dev->rx_eqe_profile);
 10236		u32 supported = dev->ethtool_ops->supported_coalesce_params;
 10237	
 10238		if (!(dev->priv_flags & (IFF_PROFILE_USEC | IFF_PROFILE_PKTS | IFF_PROFILE_COMPS)))
 10239			return 0;
 10240	
 10241		if (supported & ETHTOOL_COALESCE_RX_EQE_PROFILE) {
 10242			dev->rx_eqe_profile = kzalloc(length, GFP_KERNEL);
 10243			if (!dev->rx_eqe_profile)
 10244				return -ENOMEM;
 10245			memcpy(dev->rx_eqe_profile, rx_profile[0], length);
 10246		}
 10247		if (supported & ETHTOOL_COALESCE_RX_CQE_PROFILE) {
 10248			dev->rx_cqe_profile = kzalloc(length, GFP_KERNEL);
 10249			if (!dev->rx_cqe_profile)
 10250				return -ENOMEM;
 10251			memcpy(dev->rx_cqe_profile, rx_profile[1], length);
 10252		}
 10253		if (supported & ETHTOOL_COALESCE_TX_EQE_PROFILE) {
 10254			dev->tx_eqe_profile = kzalloc(length, GFP_KERNEL);
 10255			if (!dev->tx_eqe_profile)
 10256				return -ENOMEM;
 10257			memcpy(dev->tx_eqe_profile, tx_profile[0], length);
 10258		}
 10259		if (supported & ETHTOOL_COALESCE_TX_CQE_PROFILE) {
 10260			dev->tx_cqe_profile = kzalloc(length, GFP_KERNEL);
 10261			if (!dev->tx_cqe_profile)
 10262				return -ENOMEM;
 10263			memcpy(dev->tx_cqe_profile, tx_profile[1], length);
 10264		}
 10265	
 10266		return 0;
 10267	}
 10268
Brett Creeley April 12, 2024, 3:33 p.m. UTC | #5
On 4/11/2024 7:07 PM, Heng Qi wrote:
> Caution: This message originated from an External Source. Use proper 
> caution when opening attachments, clicking links, or responding.
> 
> 
> 在 2024/4/11 下午11:19, Brett Creeley 写道:
>>
>>
>> On 4/11/2024 7:12 AM, Heng Qi wrote:
>>> Caution: This message originated from an External Source. Use proper
>>> caution when opening attachments, clicking links, or responding.
>>>
>>>
>>> The NetDIM library, currently leveraged by an array of NICs, delivers
>>> excellent acceleration benefits. Nevertheless, NICs vary significantly
>>> in their dim profile list prerequisites.
>>>
>>> Specifically, virtio-net backends may present diverse sw or hw device
>>> implementation, making a one-size-fits-all parameter list impractical.
>>> On Alibaba Cloud, the virtio DPU's performance under the default DIM
>>> profile falls short of expectations, partly due to a mismatch in
>>> parameter configuration.
>>>
>>> I also noticed that ice/idpf/ena and other NICs have customized
>>> profilelist or placed some restrictions on dim capabilities.
>>>
>>> Motivated by this, I tried adding new params for "ethtool -C" that
>>> provides
>>> a per-device control to modify and access a device's interrupt
>>> parameters.
>>>
>>> Usage
>>> ========
>>> 1. Query the currently customized list of the device
>>>
>>> $ ethtool -c ethx
>>> ...
>>> rx-eqe-profile:
>>> {.usec =   1, .pkts = 256, .comps =   0,},
>>> {.usec =   8, .pkts = 256, .comps =   0,},
>>> {.usec =  64, .pkts = 256, .comps =   0,},
>>> {.usec = 128, .pkts = 256, .comps =   0,},
>>> {.usec = 256, .pkts = 256, .comps =   0,}
>>> rx-cqe-profile:   n/a
>>> tx-eqe-profile:   n/a
>>> tx-cqe-profile:   n/a
>>>
>>> 2. Tune
>>> $ ethtool -C ethx rx-eqe-profile 1,1,0_2,2,0_3,3,0_4,4,0_5,5,0
>>> $ ethtool -c ethx
>>> ...
>>> rx-eqe-profile:
>>> {.usec =   1, .pkts =   1, .comps =   0,},
>>> {.usec =   2, .pkts =   2, .comps =   0,},
>>> {.usec =   3, .pkts =   3, .comps =   0,},
>>> {.usec =   4, .pkts =   4, .comps =   0,},
>>> {.usec =   5, .pkts =   5, .comps =   0,}
>>> rx-cqe-profile:   n/a
>>> tx-eqe-profile:   n/a
>>> tx-cqe-profile:   n/a
>>>
>>> 3. Hint
>>> If the device does not support some type of customized dim
>>> profiles, the corresponding "n/a" will display.
>>
>> What if the user specifies a *-eqe-profile and *-cqe-profile for rx
>> and/or tx? Is that supported? If so, which one is the active profile?
> 
> 
> I think you mean GET? GET currently does not support any parameters, the
> working profile will be displayed.

Yeah, I meant the GET operation. As long as the currently in-use/working 
profile is displayed that makes sense.

> 
>>
>> Maybe I missed this, but it doesn't seem like the output from "ethtool
>> -c ethX" shows the active profile it just dumps the profile
>> configurations.
> 
> Now it is required that dev->priv_flags is set to one of
> IFF_PROFILE_{USEC, PKTS, COMPS} (which means that the
> driver supports configurable profiles) before the profile can be queried
> or do you want to query without this restriction?

No, just as I mentioned above it seems okay.

> 
> Thanks!
> 
>>
>> Thanks,
>>
>> Brett
>>
>> [snip]
>
Heng Qi April 12, 2024, 4:05 p.m. UTC | #6
在 2024/4/12 下午11:33, Brett Creeley 写道:
>
>
> On 4/11/2024 7:07 PM, Heng Qi wrote:
>> Caution: This message originated from an External Source. Use proper 
>> caution when opening attachments, clicking links, or responding.
>>
>>
>> 在 2024/4/11 下午11:19, Brett Creeley 写道:
>>>
>>>
>>> On 4/11/2024 7:12 AM, Heng Qi wrote:
>>>> Caution: This message originated from an External Source. Use proper
>>>> caution when opening attachments, clicking links, or responding.
>>>>
>>>>
>>>> The NetDIM library, currently leveraged by an array of NICs, delivers
>>>> excellent acceleration benefits. Nevertheless, NICs vary significantly
>>>> in their dim profile list prerequisites.
>>>>
>>>> Specifically, virtio-net backends may present diverse sw or hw device
>>>> implementation, making a one-size-fits-all parameter list impractical.
>>>> On Alibaba Cloud, the virtio DPU's performance under the default DIM
>>>> profile falls short of expectations, partly due to a mismatch in
>>>> parameter configuration.
>>>>
>>>> I also noticed that ice/idpf/ena and other NICs have customized
>>>> profilelist or placed some restrictions on dim capabilities.
>>>>
>>>> Motivated by this, I tried adding new params for "ethtool -C" that
>>>> provides
>>>> a per-device control to modify and access a device's interrupt
>>>> parameters.
>>>>
>>>> Usage
>>>> ========
>>>> 1. Query the currently customized list of the device
>>>>
>>>> $ ethtool -c ethx
>>>> ...
>>>> rx-eqe-profile:
>>>> {.usec =   1, .pkts = 256, .comps =   0,},
>>>> {.usec =   8, .pkts = 256, .comps =   0,},
>>>> {.usec =  64, .pkts = 256, .comps =   0,},
>>>> {.usec = 128, .pkts = 256, .comps =   0,},
>>>> {.usec = 256, .pkts = 256, .comps =   0,}
>>>> rx-cqe-profile:   n/a
>>>> tx-eqe-profile:   n/a
>>>> tx-cqe-profile:   n/a
>>>>
>>>> 2. Tune
>>>> $ ethtool -C ethx rx-eqe-profile 1,1,0_2,2,0_3,3,0_4,4,0_5,5,0
>>>> $ ethtool -c ethx
>>>> ...
>>>> rx-eqe-profile:
>>>> {.usec =   1, .pkts =   1, .comps =   0,},
>>>> {.usec =   2, .pkts =   2, .comps =   0,},
>>>> {.usec =   3, .pkts =   3, .comps =   0,},
>>>> {.usec =   4, .pkts =   4, .comps =   0,},
>>>> {.usec =   5, .pkts =   5, .comps =   0,}
>>>> rx-cqe-profile:   n/a
>>>> tx-eqe-profile:   n/a
>>>> tx-cqe-profile:   n/a
>>>>
>>>> 3. Hint
>>>> If the device does not support some type of customized dim
>>>> profiles, the corresponding "n/a" will display.
>>>
>>> What if the user specifies a *-eqe-profile and *-cqe-profile for rx
>>> and/or tx? Is that supported? If so, which one is the active profile?
>>
>>
>> I think you mean GET? GET currently does not support any parameters, the
>> working profile will be displayed.
>
> Yeah, I meant the GET operation. As long as the currently 
> in-use/working profile is displayed that makes sense.
>
>>
>>>
>>> Maybe I missed this, but it doesn't seem like the output from "ethtool
>>> -c ethX" shows the active profile it just dumps the profile
>>> configurations.
>>
>> Now it is required that dev->priv_flags is set to one of
>> IFF_PROFILE_{USEC, PKTS, COMPS} (which means that the
>> driver supports configurable profiles) before the profile can be queried
>> or do you want to query without this restriction?
>
> No, just as I mentioned above it seems okay.

Okay, then I will fix the robot warning and send out a new version.

Thanks.

>
>>
>> Thanks!
>>
>>>
>>> Thanks,
>>>
>>> Brett
>>>
>>> [snip]
>>
kernel test robot April 12, 2024, 5:44 p.m. UTC | #7
Hi Heng,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Heng-Qi/linux-dim-move-useful-macros-to-h-file/20240411-221400
base:   net-next/main
patch link:    https://lore.kernel.org/r/1712844751-53514-3-git-send-email-hengqi%40linux.alibaba.com
patch subject: [PATCH net-next v6 2/4] ethtool: provide customized dim profile management
config: openrisc-defconfig (https://download.01.org/0day-ci/archive/20240413/202404130138.7jOMaraz-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240413/202404130138.7jOMaraz-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404130138.7jOMaraz-lkp@intel.com/

All errors (new ones prefixed by >>):

   net/core/dev.c: In function 'dev_dim_profile_init':
>> net/core/dev.c:10235:63: error: 'struct net_device' has no member named 'rx_eqe_profile'
   10235 |         int length = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*dev->rx_eqe_profile);
         |                                                               ^~
   net/core/dev.c:10242:20: error: 'struct net_device' has no member named 'rx_eqe_profile'
   10242 |                 dev->rx_eqe_profile = kzalloc(length, GFP_KERNEL);
         |                    ^~
   net/core/dev.c:10243:25: error: 'struct net_device' has no member named 'rx_eqe_profile'
   10243 |                 if (!dev->rx_eqe_profile)
         |                         ^~
   net/core/dev.c:10245:27: error: 'struct net_device' has no member named 'rx_eqe_profile'
   10245 |                 memcpy(dev->rx_eqe_profile, rx_profile[0], length);
         |                           ^~
>> net/core/dev.c:10248:20: error: 'struct net_device' has no member named 'rx_cqe_profile'
   10248 |                 dev->rx_cqe_profile = kzalloc(length, GFP_KERNEL);
         |                    ^~
   net/core/dev.c:10249:25: error: 'struct net_device' has no member named 'rx_cqe_profile'
   10249 |                 if (!dev->rx_cqe_profile)
         |                         ^~
   net/core/dev.c:10251:27: error: 'struct net_device' has no member named 'rx_cqe_profile'
   10251 |                 memcpy(dev->rx_cqe_profile, rx_profile[1], length);
         |                           ^~
>> net/core/dev.c:10254:20: error: 'struct net_device' has no member named 'tx_eqe_profile'
   10254 |                 dev->tx_eqe_profile = kzalloc(length, GFP_KERNEL);
         |                    ^~
   net/core/dev.c:10255:25: error: 'struct net_device' has no member named 'tx_eqe_profile'
   10255 |                 if (!dev->tx_eqe_profile)
         |                         ^~
   net/core/dev.c:10257:27: error: 'struct net_device' has no member named 'tx_eqe_profile'
   10257 |                 memcpy(dev->tx_eqe_profile, tx_profile[0], length);
         |                           ^~
>> net/core/dev.c:10260:20: error: 'struct net_device' has no member named 'tx_cqe_profile'
   10260 |                 dev->tx_cqe_profile = kzalloc(length, GFP_KERNEL);
         |                    ^~
   net/core/dev.c:10261:25: error: 'struct net_device' has no member named 'tx_cqe_profile'
   10261 |                 if (!dev->tx_cqe_profile)
         |                         ^~
   net/core/dev.c:10263:27: error: 'struct net_device' has no member named 'tx_cqe_profile'
   10263 |                 memcpy(dev->tx_cqe_profile, tx_profile[1], length);
         |                           ^~
   net/core/dev.c: In function 'netif_free_profile':
   net/core/dev.c:11063:26: error: 'struct net_device' has no member named 'rx_eqe_profile'
   11063 |                 kfree(dev->rx_eqe_profile);
         |                          ^~
   net/core/dev.c:11066:26: error: 'struct net_device' has no member named 'rx_cqe_profile'
   11066 |                 kfree(dev->rx_cqe_profile);
         |                          ^~
   net/core/dev.c:11069:26: error: 'struct net_device' has no member named 'tx_eqe_profile'
   11069 |                 kfree(dev->tx_eqe_profile);
         |                          ^~
   net/core/dev.c:11072:26: error: 'struct net_device' has no member named 'tx_cqe_profile'
   11072 |                 kfree(dev->tx_cqe_profile);
         |                          ^~
--
   net/ethtool/coalesce.c: In function 'coalesce_fill_reply':
>> net/ethtool/coalesce.c:268:37: error: 'struct net_device' has no member named 'rx_eqe_profile'
     268 |                                  dev->rx_eqe_profile, supported) ||
         |                                     ^~
>> net/ethtool/coalesce.c:270:37: error: 'struct net_device' has no member named 'rx_cqe_profile'
     270 |                                  dev->rx_cqe_profile, supported) ||
         |                                     ^~
>> net/ethtool/coalesce.c:272:37: error: 'struct net_device' has no member named 'tx_eqe_profile'
     272 |                                  dev->tx_eqe_profile, supported) ||
         |                                     ^~
>> net/ethtool/coalesce.c:274:37: error: 'struct net_device' has no member named 'tx_cqe_profile'
     274 |                                  dev->tx_cqe_profile, supported))
         |                                     ^~
   net/ethtool/coalesce.c: In function '__ethnl_set_coalesce':
   net/ethtool/coalesce.c:479:44: error: 'struct net_device' has no member named 'rx_eqe_profile'
     479 |         ret = ethnl_update_profile(dev, dev->rx_eqe_profile,
         |                                            ^~
   net/ethtool/coalesce.c:484:44: error: 'struct net_device' has no member named 'rx_cqe_profile'
     484 |         ret = ethnl_update_profile(dev, dev->rx_cqe_profile,
         |                                            ^~
   net/ethtool/coalesce.c:489:44: error: 'struct net_device' has no member named 'tx_eqe_profile'
     489 |         ret = ethnl_update_profile(dev, dev->tx_eqe_profile,
         |                                            ^~
   net/ethtool/coalesce.c:494:44: error: 'struct net_device' has no member named 'tx_cqe_profile'
     494 |         ret = ethnl_update_profile(dev, dev->tx_cqe_profile,
         |                                            ^~


vim +10235 net/core/dev.c

 10232	
 10233	static int dev_dim_profile_init(struct net_device *dev)
 10234	{
 10235		int length = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*dev->rx_eqe_profile);
 10236		u32 supported = dev->ethtool_ops->supported_coalesce_params;
 10237	
 10238		if (!(dev->priv_flags & (IFF_PROFILE_USEC | IFF_PROFILE_PKTS | IFF_PROFILE_COMPS)))
 10239			return 0;
 10240	
 10241		if (supported & ETHTOOL_COALESCE_RX_EQE_PROFILE) {
 10242			dev->rx_eqe_profile = kzalloc(length, GFP_KERNEL);
 10243			if (!dev->rx_eqe_profile)
 10244				return -ENOMEM;
 10245			memcpy(dev->rx_eqe_profile, rx_profile[0], length);
 10246		}
 10247		if (supported & ETHTOOL_COALESCE_RX_CQE_PROFILE) {
 10248			dev->rx_cqe_profile = kzalloc(length, GFP_KERNEL);
 10249			if (!dev->rx_cqe_profile)
 10250				return -ENOMEM;
 10251			memcpy(dev->rx_cqe_profile, rx_profile[1], length);
 10252		}
 10253		if (supported & ETHTOOL_COALESCE_TX_EQE_PROFILE) {
 10254			dev->tx_eqe_profile = kzalloc(length, GFP_KERNEL);
 10255			if (!dev->tx_eqe_profile)
 10256				return -ENOMEM;
 10257			memcpy(dev->tx_eqe_profile, tx_profile[0], length);
 10258		}
 10259		if (supported & ETHTOOL_COALESCE_TX_CQE_PROFILE) {
 10260			dev->tx_cqe_profile = kzalloc(length, GFP_KERNEL);
 10261			if (!dev->tx_cqe_profile)
 10262				return -ENOMEM;
 10263			memcpy(dev->tx_cqe_profile, tx_profile[1], length);
 10264		}
 10265	
 10266		return 0;
 10267	}
 10268
Jakub Kicinski April 13, 2024, 2:26 a.m. UTC | #8
On Thu, 11 Apr 2024 22:12:29 +0800 Heng Qi wrote:
> +#include <linux/dim.h>
>  #include <net/net_trackers.h>
>  #include <net/net_debug.h>
>  #include <net/dropreason-core.h>
> @@ -1649,6 +1650,9 @@ struct net_device_ops {
>   * @IFF_SEE_ALL_HWTSTAMP_REQUESTS: device wants to see calls to
>   *	ndo_hwtstamp_set() for all timestamp requests regardless of source,
>   *	even if those aren't HWTSTAMP_SOURCE_NETDEV.
> + * @IFF_PROFILE_USEC: device supports adjusting the DIM profile's usec field
> + * @IFF_PROFILE_PKTS: device supports adjusting the DIM profile's pkts field
> + * @IFF_PROFILE_COMPS: device supports adjusting the DIM profile's comps field
>   */
>  enum netdev_priv_flags {
>  	IFF_802_1Q_VLAN			= 1<<0,
> @@ -1685,6 +1689,9 @@ enum netdev_priv_flags {
>  	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
>  	IFF_CHANGE_PROTO_DOWN		= BIT_ULL(32),
>  	IFF_SEE_ALL_HWTSTAMP_REQUESTS	= BIT_ULL(33),
> +	IFF_PROFILE_USEC		= BIT_ULL(34),
> +	IFF_PROFILE_PKTS		= BIT_ULL(35),
> +	IFF_PROFILE_COMPS		= BIT_ULL(36),
>  };
>  
>  #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
> @@ -2400,6 +2407,14 @@ struct net_device {
>  	/** @page_pools: page pools created for this netdevice */
>  	struct hlist_head	page_pools;
>  #endif
> +
> +#if IS_ENABLED(CONFIG_DIMLIB)
> +	/* DIM profile lists for different dim cq modes */
> +	struct dim_cq_moder *rx_eqe_profile;
> +	struct dim_cq_moder *rx_cqe_profile;
> +	struct dim_cq_moder *tx_eqe_profile;
> +	struct dim_cq_moder *tx_cqe_profile;
> +#endif

just one pointer to a new wrapper struct, put the pointers and a flag
field in there.

netdevice.h is included by thousands of files, please use a forward
declaration for the type and avoid including dim.h
Jakub Kicinski April 13, 2024, 2:27 a.m. UTC | #9
On Thu, 11 Apr 2024 22:12:29 +0800 Heng Qi wrote:
> +        name: usec
> +        type: u16
> +      -
> +        name: pkts
> +        type: u16
> +      -
> +        name: comps
> +        type: u16

I think I mentioned already - u32 please.
Heng Qi April 13, 2024, 10:14 a.m. UTC | #10
在 2024/4/13 上午10:26, Jakub Kicinski 写道:
> On Thu, 11 Apr 2024 22:12:29 +0800 Heng Qi wrote:
>> +#include <linux/dim.h>
>>   #include <net/net_trackers.h>
>>   #include <net/net_debug.h>
>>   #include <net/dropreason-core.h>
>> @@ -1649,6 +1650,9 @@ struct net_device_ops {
>>    * @IFF_SEE_ALL_HWTSTAMP_REQUESTS: device wants to see calls to
>>    *	ndo_hwtstamp_set() for all timestamp requests regardless of source,
>>    *	even if those aren't HWTSTAMP_SOURCE_NETDEV.
>> + * @IFF_PROFILE_USEC: device supports adjusting the DIM profile's usec field
>> + * @IFF_PROFILE_PKTS: device supports adjusting the DIM profile's pkts field
>> + * @IFF_PROFILE_COMPS: device supports adjusting the DIM profile's comps field
>>    */
>>   enum netdev_priv_flags {
>>   	IFF_802_1Q_VLAN			= 1<<0,
>> @@ -1685,6 +1689,9 @@ enum netdev_priv_flags {
>>   	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
>>   	IFF_CHANGE_PROTO_DOWN		= BIT_ULL(32),
>>   	IFF_SEE_ALL_HWTSTAMP_REQUESTS	= BIT_ULL(33),
>> +	IFF_PROFILE_USEC		= BIT_ULL(34),
>> +	IFF_PROFILE_PKTS		= BIT_ULL(35),
>> +	IFF_PROFILE_COMPS		= BIT_ULL(36),
>>   };
>>   
>>   #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
>> @@ -2400,6 +2407,14 @@ struct net_device {
>>   	/** @page_pools: page pools created for this netdevice */
>>   	struct hlist_head	page_pools;
>>   #endif
>> +
>> +#if IS_ENABLED(CONFIG_DIMLIB)
>> +	/* DIM profile lists for different dim cq modes */
>> +	struct dim_cq_moder *rx_eqe_profile;
>> +	struct dim_cq_moder *rx_cqe_profile;
>> +	struct dim_cq_moder *tx_eqe_profile;
>> +	struct dim_cq_moder *tx_cqe_profile;
>> +#endif
> just one pointer to a new wrapper struct, put the pointers and a flag
> field in there.
>
> netdevice.h is included by thousands of files, please use a forward
> declaration for the type and avoid including dim.h

I will update this.

Thanks for the constructive comments!
diff mbox series

Patch

diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index 87ae7b3..1a560ff 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -413,6 +413,18 @@  attribute-sets:
       -
         name: combined-count
         type: u32
+  -
+    name: moderation
+    attributes:
+      -
+        name: usec
+        type: u16
+      -
+        name: pkts
+        type: u16
+      -
+        name: comps
+        type: u16
 
   -
     name: coalesce
@@ -502,6 +514,23 @@  attribute-sets:
       -
         name: tx-aggr-time-usecs
         type: u32
+      -
+        name: rx-eqe-profile
+        type: nest
+        nested-attributes: moderation
+      -
+        name: rx-cqe-profile
+        type: nest
+        nested-attributes: moderation
+      -
+        name: tx-eqe-profile
+        type: nest
+        nested-attributes: moderation
+      -
+        name: tx-cqe-profile
+        type: nest
+        nested-attributes: moderation
+
   -
     name: pause-stat
     attributes:
@@ -1313,6 +1342,10 @@  operations:
             - tx-aggr-max-bytes
             - tx-aggr-max-frames
             - tx-aggr-time-usecs
+            - rx-eqe-profile
+            - rx-cqe-profile
+            - tx-eqe-profile
+            - tx-cqe-profile
       dump: *coalesce-get-op
     -
       name: coalesce-set
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index 5dc42f7..4d9eecf 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -1040,6 +1040,10 @@  Kernel response contents:
   ``ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES``     u32     max aggr size, Tx
   ``ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES``    u32     max aggr packets, Tx
   ``ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS``    u32     time (us), aggr, Tx
+  ``ETHTOOL_A_COALESCE_RX_EQE_PROFILE``        nested  profile of DIM EQE, Rx
+  ``ETHTOOL_A_COALESCE_RX_CQE_PROFILE``        nested  profile of DIM CQE, Rx
+  ``ETHTOOL_A_COALESCE_TX_EQE_PROFILE``        nested  profile of DIM EQE, Tx
+  ``ETHTOOL_A_COALESCE_TX_CQE_PROFILE``        nested  profile of DIM CQE, Tx
   ===========================================  ======  =======================
 
 Attributes are only included in reply if their value is not zero or the
@@ -1105,6 +1109,10 @@  Request contents:
   ``ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES``     u32     max aggr size, Tx
   ``ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES``    u32     max aggr packets, Tx
   ``ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS``    u32     time (us), aggr, Tx
+  ``ETHTOOL_A_COALESCE_RX_EQE_PROFILE``        nested  profile of DIM EQE, Rx
+  ``ETHTOOL_A_COALESCE_RX_CQE_PROFILE``        nested  profile of DIM CQE, Rx
+  ``ETHTOOL_A_COALESCE_TX_EQE_PROFILE``        nested  profile of DIM EQE, Tx
+  ``ETHTOOL_A_COALESCE_TX_CQE_PROFILE``        nested  profile of DIM CQE, Tx
   ===========================================  ======  =======================
 
 Request is rejected if it attributes declared as unsupported by driver (i.e.
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 6fd9107..1dcfbe5 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -18,6 +18,7 @@ 
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
 #include <uapi/linux/ethtool.h>
+#include <linux/dim.h>
 
 struct compat_ethtool_rx_flow_spec {
 	u32		flow_type;
@@ -284,7 +285,11 @@  bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
 #define ETHTOOL_COALESCE_TX_AGGR_MAX_BYTES	BIT(24)
 #define ETHTOOL_COALESCE_TX_AGGR_MAX_FRAMES	BIT(25)
 #define ETHTOOL_COALESCE_TX_AGGR_TIME_USECS	BIT(26)
-#define ETHTOOL_COALESCE_ALL_PARAMS		GENMASK(26, 0)
+#define ETHTOOL_COALESCE_RX_EQE_PROFILE         BIT(27)
+#define ETHTOOL_COALESCE_RX_CQE_PROFILE         BIT(28)
+#define ETHTOOL_COALESCE_TX_EQE_PROFILE         BIT(29)
+#define ETHTOOL_COALESCE_TX_CQE_PROFILE         BIT(30)
+#define ETHTOOL_COALESCE_ALL_PARAMS		GENMASK(30, 0)
 
 #define ETHTOOL_COALESCE_USECS						\
 	(ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_TX_USECS)
@@ -316,6 +321,11 @@  bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
 	(ETHTOOL_COALESCE_TX_AGGR_MAX_BYTES |	\
 	 ETHTOOL_COALESCE_TX_AGGR_MAX_FRAMES |	\
 	 ETHTOOL_COALESCE_TX_AGGR_TIME_USECS)
+#define ETHTOOL_COALESCE_PROFILE		\
+	(ETHTOOL_COALESCE_RX_EQE_PROFILE |	\
+	 ETHTOOL_COALESCE_RX_CQE_PROFILE |	\
+	 ETHTOOL_COALESCE_TX_EQE_PROFILE |	\
+	 ETHTOOL_COALESCE_TX_CQE_PROFILE)
 
 #define ETHTOOL_STAT_NOT_SET	(~0ULL)
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d45f330..d2f499a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -48,6 +48,7 @@ 
 #include <uapi/linux/netdev.h>
 #include <linux/hashtable.h>
 #include <linux/rbtree.h>
+#include <linux/dim.h>
 #include <net/net_trackers.h>
 #include <net/net_debug.h>
 #include <net/dropreason-core.h>
@@ -1649,6 +1650,9 @@  struct net_device_ops {
  * @IFF_SEE_ALL_HWTSTAMP_REQUESTS: device wants to see calls to
  *	ndo_hwtstamp_set() for all timestamp requests regardless of source,
  *	even if those aren't HWTSTAMP_SOURCE_NETDEV.
+ * @IFF_PROFILE_USEC: device supports adjusting the DIM profile's usec field
+ * @IFF_PROFILE_PKTS: device supports adjusting the DIM profile's pkts field
+ * @IFF_PROFILE_COMPS: device supports adjusting the DIM profile's comps field
  */
 enum netdev_priv_flags {
 	IFF_802_1Q_VLAN			= 1<<0,
@@ -1685,6 +1689,9 @@  enum netdev_priv_flags {
 	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
 	IFF_CHANGE_PROTO_DOWN		= BIT_ULL(32),
 	IFF_SEE_ALL_HWTSTAMP_REQUESTS	= BIT_ULL(33),
+	IFF_PROFILE_USEC		= BIT_ULL(34),
+	IFF_PROFILE_PKTS		= BIT_ULL(35),
+	IFF_PROFILE_COMPS		= BIT_ULL(36),
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
@@ -2400,6 +2407,14 @@  struct net_device {
 	/** @page_pools: page pools created for this netdevice */
 	struct hlist_head	page_pools;
 #endif
+
+#if IS_ENABLED(CONFIG_DIMLIB)
+	/* DIM profile lists for different dim cq modes */
+	struct dim_cq_moder *rx_eqe_profile;
+	struct dim_cq_moder *rx_cqe_profile;
+	struct dim_cq_moder *tx_eqe_profile;
+	struct dim_cq_moder *tx_cqe_profile;
+#endif
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 23e225f..81c6d9e 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -416,12 +416,36 @@  enum {
 	ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES,		/* u32 */
 	ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,		/* u32 */
 	ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_EQE_PROFILE,              /* nest - _A_MODERATIONS_MODERATION */
+	ETHTOOL_A_COALESCE_RX_CQE_PROFILE,              /* nest - _A_MODERATIONS_MODERATION */
+	ETHTOOL_A_COALESCE_TX_EQE_PROFILE,              /* nest - _A_MODERATIONS_MODERATION */
+	ETHTOOL_A_COALESCE_TX_CQE_PROFILE,              /* nest - _A_MODERATIONS_MODERATION */
 
 	/* add new constants above here */
 	__ETHTOOL_A_COALESCE_CNT,
 	ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
 };
 
+enum {
+	ETHTOOL_A_MODERATIONS_UNSPEC,
+	ETHTOOL_A_MODERATIONS_MODERATION,		/* nest, _A_MODERATION_* */
+
+	/* add new constants above here */
+	__ETHTOOL_A_MODERATIONS_CNT,
+	ETHTOOL_A_MODERATIONS_MAX = (__ETHTOOL_A_MODERATIONS_CNT - 1)
+};
+
+enum {
+	ETHTOOL_A_MODERATION_UNSPEC,
+	ETHTOOL_A_MODERATION_USEC,			/* u16 */
+	ETHTOOL_A_MODERATION_PKTS,			/* u16 */
+	ETHTOOL_A_MODERATION_COMPS,			/* u16 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_MODERATION_CNT,
+	ETHTOOL_A_MODERATION_MAX = (__ETHTOOL_A_MODERATION_CNT - 1)
+};
+
 /* PAUSE */
 
 enum {
diff --git a/net/core/dev.c b/net/core/dev.c
index 854a3a2..bc38f33 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -154,6 +154,7 @@ 
 #include <linux/pm_runtime.h>
 #include <linux/prandom.h>
 #include <linux/once_lite.h>
+#include <linux/ethtool.h>
 #include <net/netdev_rx_queue.h>
 #include <net/page_pool/types.h>
 #include <net/page_pool/helpers.h>
@@ -10229,6 +10230,42 @@  static void netdev_do_free_pcpu_stats(struct net_device *dev)
 	}
 }
 
+static int dev_dim_profile_init(struct net_device *dev)
+{
+	int length = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*dev->rx_eqe_profile);
+	u32 supported = dev->ethtool_ops->supported_coalesce_params;
+
+	if (!(dev->priv_flags & (IFF_PROFILE_USEC | IFF_PROFILE_PKTS | IFF_PROFILE_COMPS)))
+		return 0;
+
+	if (supported & ETHTOOL_COALESCE_RX_EQE_PROFILE) {
+		dev->rx_eqe_profile = kzalloc(length, GFP_KERNEL);
+		if (!dev->rx_eqe_profile)
+			return -ENOMEM;
+		memcpy(dev->rx_eqe_profile, rx_profile[0], length);
+	}
+	if (supported & ETHTOOL_COALESCE_RX_CQE_PROFILE) {
+		dev->rx_cqe_profile = kzalloc(length, GFP_KERNEL);
+		if (!dev->rx_cqe_profile)
+			return -ENOMEM;
+		memcpy(dev->rx_cqe_profile, rx_profile[1], length);
+	}
+	if (supported & ETHTOOL_COALESCE_TX_EQE_PROFILE) {
+		dev->tx_eqe_profile = kzalloc(length, GFP_KERNEL);
+		if (!dev->tx_eqe_profile)
+			return -ENOMEM;
+		memcpy(dev->tx_eqe_profile, tx_profile[0], length);
+	}
+	if (supported & ETHTOOL_COALESCE_TX_CQE_PROFILE) {
+		dev->tx_cqe_profile = kzalloc(length, GFP_KERNEL);
+		if (!dev->tx_cqe_profile)
+			return -ENOMEM;
+		memcpy(dev->tx_cqe_profile, tx_profile[1], length);
+	}
+
+	return 0;
+}
+
 /**
  * register_netdevice() - register a network device
  * @dev: device to register
@@ -10258,6 +10295,10 @@  int register_netdevice(struct net_device *dev)
 	if (ret)
 		return ret;
 
+	ret = dev_dim_profile_init(dev);
+	if (ret)
+		return ret;
+
 	spin_lock_init(&dev->addr_list_lock);
 	netdev_set_addr_lockdep_class(dev);
 
@@ -11011,6 +11052,26 @@  struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 }
 EXPORT_SYMBOL(alloc_netdev_mqs);
 
+static void netif_free_profile(struct net_device *dev)
+{
+	u32 supported = dev->ethtool_ops->supported_coalesce_params;
+
+	if (!(dev->priv_flags & (IFF_PROFILE_USEC | IFF_PROFILE_PKTS | IFF_PROFILE_COMPS)))
+		return;
+
+	if (supported & ETHTOOL_COALESCE_RX_EQE_PROFILE)
+		kfree(dev->rx_eqe_profile);
+
+	if (supported & ETHTOOL_COALESCE_RX_CQE_PROFILE)
+		kfree(dev->rx_cqe_profile);
+
+	if (supported & ETHTOOL_COALESCE_TX_EQE_PROFILE)
+		kfree(dev->tx_eqe_profile);
+
+	if (supported & ETHTOOL_COALESCE_TX_CQE_PROFILE)
+		kfree(dev->tx_cqe_profile);
+}
+
 /**
  * free_netdev - free network device
  * @dev: device
@@ -11036,6 +11097,8 @@  void free_netdev(struct net_device *dev)
 		return;
 	}
 
+	netif_free_profile(dev);
+
 	netif_free_tx_queues(dev);
 	netif_free_rx_queues(dev);
 
diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c
index 83112c1..7b542c3e 100644
--- a/net/ethtool/coalesce.c
+++ b/net/ethtool/coalesce.c
@@ -51,6 +51,10 @@  static u32 attr_to_mask(unsigned int attr_type)
 __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_RX_EQE_PROFILE);
+__CHECK_SUPPORTED_OFFSET(COALESCE_RX_CQE_PROFILE);
+__CHECK_SUPPORTED_OFFSET(COALESCE_TX_EQE_PROFILE);
+__CHECK_SUPPORTED_OFFSET(COALESCE_TX_CQE_PROFILE);
 
 const struct nla_policy ethnl_coalesce_get_policy[] = {
 	[ETHTOOL_A_COALESCE_HEADER]		=
@@ -82,6 +86,13 @@  static int coalesce_prepare_data(const struct ethnl_req_info *req_base,
 static int coalesce_reply_size(const struct ethnl_req_info *req_base,
 			       const struct ethnl_reply_data *reply_base)
 {
+	int modersz = nla_total_size(0) + /* _MODERATIONS_MODERATION, nest */
+		      nla_total_size(sizeof(u16)) + /* _MODERATION_USEC */
+		      nla_total_size(sizeof(u16)) + /* _MODERATION_PKTS */
+		      nla_total_size(sizeof(u16));  /* _MODERATION_COMPS */
+	int total_modersz = nla_total_size(0) +  /* _{R,T}X_{E,C}QE_PROFILE, nest */
+			    modersz * NET_DIM_PARAMS_NUM_PROFILES;
+
 	return nla_total_size(sizeof(u32)) +	/* _RX_USECS */
 	       nla_total_size(sizeof(u32)) +	/* _RX_MAX_FRAMES */
 	       nla_total_size(sizeof(u32)) +	/* _RX_USECS_IRQ */
@@ -108,7 +119,8 @@  static int coalesce_reply_size(const struct ethnl_req_info *req_base,
 	       nla_total_size(sizeof(u8)) +	/* _USE_CQE_MODE_RX */
 	       nla_total_size(sizeof(u32)) +	/* _TX_AGGR_MAX_BYTES */
 	       nla_total_size(sizeof(u32)) +	/* _TX_AGGR_MAX_FRAMES */
-	       nla_total_size(sizeof(u32));	/* _TX_AGGR_TIME_USECS */
+	       nla_total_size(sizeof(u32)) +	/* _TX_AGGR_TIME_USECS */
+	       total_modersz * 4;		/* _{R,T}X_{E,C}QE_PROFILE */
 }
 
 static bool coalesce_put_u32(struct sk_buff *skb, u16 attr_type, u32 val,
@@ -127,6 +139,67 @@  static bool coalesce_put_bool(struct sk_buff *skb, u16 attr_type, u32 val,
 	return nla_put_u8(skb, attr_type, !!val);
 }
 
+/**
+ * coalesce_put_profile - fill reply with a nla nest with four child nla nests.
+ * @skb: socket buffer the message is stored in
+ * @attr_type: nest attr type ETHTOOL_A_COALESCE_*X_*QE_PROFILE
+ * @profile: data passed to userspace
+ * @supported_params: modifiable parameters supported by the driver
+ *
+ * Put a dim profile nest attribute. Refer to ETHTOOL_A_MODERATIONS_MODERATION.
+ *
+ * Returns false to indicate successful placement or no placement, and
+ * returns true to pass the -EMSGSIZE error to the wrapper.
+ */
+static bool coalesce_put_profile(struct sk_buff *skb, u16 attr_type,
+				 const struct dim_cq_moder *profile,
+				 u32 supported_params)
+{
+	struct nlattr *profile_attr, *moder_attr;
+	bool valid = false, emsg = !!-EMSGSIZE;
+	int i;
+
+	if (!profile)
+		return false;
+
+	for (i = 0; i < NET_DIM_PARAMS_NUM_PROFILES; i++) {
+		if (profile[i].usec || profile[i].pkts || profile[i].comps) {
+			valid = true;
+			break;
+		}
+	}
+
+	if (!valid || !(supported_params & attr_to_mask(attr_type)))
+		return false;
+
+	profile_attr = nla_nest_start(skb, attr_type);
+	if (!profile_attr)
+		return emsg;
+
+	for (i = 0; i < NET_DIM_PARAMS_NUM_PROFILES; i++) {
+		moder_attr = nla_nest_start(skb, ETHTOOL_A_MODERATIONS_MODERATION);
+		if (!moder_attr)
+			goto nla_cancel_profile;
+
+		if (nla_put_u16(skb, ETHTOOL_A_MODERATION_USEC, profile[i].usec) ||
+		    nla_put_u16(skb, ETHTOOL_A_MODERATION_PKTS, profile[i].pkts) ||
+		    nla_put_u16(skb, ETHTOOL_A_MODERATION_COMPS, profile[i].comps))
+			goto nla_cancel_moder;
+
+		nla_nest_end(skb, moder_attr);
+	}
+
+	nla_nest_end(skb, profile_attr);
+
+	return 0;
+
+nla_cancel_moder:
+	nla_nest_cancel(skb, moder_attr);
+nla_cancel_profile:
+	nla_nest_cancel(skb, profile_attr);
+	return emsg;
+}
+
 static int coalesce_fill_reply(struct sk_buff *skb,
 			       const struct ethnl_req_info *req_base,
 			       const struct ethnl_reply_data *reply_base)
@@ -134,6 +207,7 @@  static int coalesce_fill_reply(struct sk_buff *skb,
 	const struct coalesce_reply_data *data = COALESCE_REPDATA(reply_base);
 	const struct kernel_ethtool_coalesce *kcoal = &data->kernel_coalesce;
 	const struct ethtool_coalesce *coal = &data->coalesce;
+	struct net_device *dev = req_base->dev;
 	u32 supported = data->supported_params;
 
 	if (coalesce_put_u32(skb, ETHTOOL_A_COALESCE_RX_USECS,
@@ -189,7 +263,15 @@  static int coalesce_fill_reply(struct sk_buff *skb,
 	    coalesce_put_u32(skb, ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,
 			     kcoal->tx_aggr_max_frames, supported) ||
 	    coalesce_put_u32(skb, ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
-			     kcoal->tx_aggr_time_usecs, supported))
+			     kcoal->tx_aggr_time_usecs, supported) ||
+	    coalesce_put_profile(skb, ETHTOOL_A_COALESCE_RX_EQE_PROFILE,
+				 dev->rx_eqe_profile, supported) ||
+	    coalesce_put_profile(skb, ETHTOOL_A_COALESCE_RX_CQE_PROFILE,
+				 dev->rx_cqe_profile, supported) ||
+	    coalesce_put_profile(skb, ETHTOOL_A_COALESCE_TX_EQE_PROFILE,
+				 dev->tx_eqe_profile, supported) ||
+	    coalesce_put_profile(skb, ETHTOOL_A_COALESCE_TX_CQE_PROFILE,
+				 dev->tx_cqe_profile, supported))
 		return -EMSGSIZE;
 
 	return 0;
@@ -227,6 +309,16 @@  static int coalesce_fill_reply(struct sk_buff *skb,
 	[ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES] = { .type = NLA_U32 },
 	[ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES] = { .type = NLA_U32 },
 	[ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS] = { .type = NLA_U32 },
+	[ETHTOOL_A_COALESCE_RX_EQE_PROFILE]     = { .type = NLA_NESTED },
+	[ETHTOOL_A_COALESCE_RX_CQE_PROFILE]     = { .type = NLA_NESTED },
+	[ETHTOOL_A_COALESCE_TX_EQE_PROFILE]     = { .type = NLA_NESTED },
+	[ETHTOOL_A_COALESCE_TX_CQE_PROFILE]     = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy coalesce_set_profile_policy[] = {
+	[ETHTOOL_A_MODERATION_USEC]	= {.type = NLA_U16},
+	[ETHTOOL_A_MODERATION_PKTS]	= {.type = NLA_U16},
+	[ETHTOOL_A_MODERATION_COMPS]	= {.type = NLA_U16},
 };
 
 static int
@@ -253,6 +345,73 @@  static int coalesce_fill_reply(struct sk_buff *skb,
 	return 1;
 }
 
+/**
+ * ethnl_update_profile - get a nla nest with four child nla nests from userspace.
+ * @dst: data get from the driver and modified by ethnl_update_profile.
+ * @nests: nest attr ETHTOOL_A_COALESCE_*X_*QE_PROFILE to set driver's profile.
+ * @mod: whether the data is modified
+ * @extack: Netlink extended ack
+ *
+ * Layout of nests:
+ *   Nested ETHTOOL_A_COALESCE_*X_*QE_PROFILE attr
+ *     Nested ETHTOOL_A_MODERATIONS_MODERATION attr
+ *       ETHTOOL_A_MODERATION_USEC attr
+ *       ETHTOOL_A_MODERATION_PKTS attr
+ *       ETHTOOL_A_MODERATION_COMPS attr
+ *     ...
+ *     Nested ETHTOOL_A_MODERATIONS_MODERATION attr
+ *       ETHTOOL_A_MODERATION_USEC attr
+ *       ETHTOOL_A_MODERATION_PKTS attr
+ *       ETHTOOL_A_MODERATION_COMPS attr
+ *
+ * Returns 0 on success or a negative error code.
+ */
+static inline int ethnl_update_profile(struct net_device *dev,
+				       struct dim_cq_moder *dst,
+				       const struct nlattr *nests,
+				       struct netlink_ext_ack *extack)
+{
+	struct nlattr *tb_moder[ARRAY_SIZE(coalesce_set_profile_policy)];
+	struct dim_cq_moder profile[NET_DIM_PARAMS_NUM_PROFILES];
+	struct nlattr *nest;
+	int ret, rem, i = 0;
+
+	if (!nests)
+		return 0;
+
+	if (!dst)
+		return -EOPNOTSUPP;
+
+	nla_for_each_nested_type(nest, ETHTOOL_A_MODERATIONS_MODERATION, nests, rem) {
+		ret = nla_parse_nested(tb_moder,
+				       ARRAY_SIZE(coalesce_set_profile_policy) - 1,
+				       nest, coalesce_set_profile_policy,
+				       extack);
+		if (ret)
+			return ret;
+
+		if (NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_USEC) ||
+		    NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_PKTS) ||
+		    NL_REQ_ATTR_CHECK(extack, nest, tb_moder, ETHTOOL_A_MODERATION_COMPS))
+			return -EINVAL;
+
+		profile[i].usec = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_USEC]);
+		profile[i].pkts = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_PKTS]);
+		profile[i].comps = nla_get_u16(tb_moder[ETHTOOL_A_MODERATION_COMPS]);
+
+		if ((dst[i].usec != profile[i].usec && !(dev->priv_flags & IFF_PROFILE_USEC)) ||
+		    (dst[i].pkts != profile[i].pkts && !(dev->priv_flags & IFF_PROFILE_PKTS)) ||
+		    (dst[i].comps != profile[i].comps && !(dev->priv_flags & IFF_PROFILE_COMPS)))
+			return -EOPNOTSUPP;
+
+		i++;
+	}
+
+	memcpy(dst, profile, sizeof(profile));
+
+	return 0;
+}
+
 static int
 __ethnl_set_coalesce(struct ethnl_req_info *req_info, struct genl_info *info,
 		     bool *dual_change)
@@ -317,6 +476,27 @@  static int coalesce_fill_reply(struct sk_buff *skb,
 	ethnl_update_u32(&kernel_coalesce.tx_aggr_time_usecs,
 			 tb[ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS], &mod);
 
+	ret = ethnl_update_profile(dev, dev->rx_eqe_profile,
+				   tb[ETHTOOL_A_COALESCE_RX_EQE_PROFILE],
+				   info->extack);
+	if (ret < 0)
+		return ret;
+	ret = ethnl_update_profile(dev, dev->rx_cqe_profile,
+				   tb[ETHTOOL_A_COALESCE_RX_CQE_PROFILE],
+				   info->extack);
+	if (ret < 0)
+		return ret;
+	ret = ethnl_update_profile(dev, dev->tx_eqe_profile,
+				   tb[ETHTOOL_A_COALESCE_TX_EQE_PROFILE],
+				   info->extack);
+	if (ret < 0)
+		return ret;
+	ret = ethnl_update_profile(dev, dev->tx_cqe_profile,
+				   tb[ETHTOOL_A_COALESCE_TX_CQE_PROFILE],
+				   info->extack);
+	if (ret < 0)
+		return ret;
+
 	/* Update operation modes */
 	ethnl_update_bool32(&coalesce.use_adaptive_rx_coalesce,
 			    tb[ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX], &mod_mode);