Added macros and headers required by MLX4/5 drivers on RHEL7.5
authorVladimir Sokolovsky <vlad@mellanox.com>
Tue, 17 Jul 2018 18:42:51 +0000 (13:42 -0500)
committerVladimir Sokolovsky <vlad@mellanox.com>
Fri, 20 Jul 2018 20:57:01 +0000 (15:57 -0500)
Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
config/rdma.m4
include/linux/bpf.h [new file with mode: 0644]
include/linux/compat-2.6.h
include/linux/compat-4.17.h [new file with mode: 0644]
include/linux/dcbnl.h [new file with mode: 0644]
include/linux/net_dim.h [new file with mode: 0644]
include/linux/netdevice.h

index 2773ecb..6469093 100644 (file)
@@ -3180,6 +3180,23 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
+       AC_MSG_CHECKING([if struct ifla_vf_stats has rx_dropped])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/if_link.h>
+       ],[
+               struct ifla_vf_stats stat = {
+                       .rx_dropped = 0,
+                       };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_IFLA_VF_STATS_RX_DROPPED, 1,
+                         [struct ifla_vf_stats has rx_dropped])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
        AC_MSG_CHECKING([if struct net_device_ops has ndo_set_vf_guid])
        LB_LINUX_TRY_COMPILE([
                #include <linux/netdevice.h>
@@ -3246,6 +3263,23 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
+       AC_MSG_CHECKING([if struct xdp_buff has rxq])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/filter.h>
+       ],[
+               struct xdp_buff x = {
+                       .rxq = NULL,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XDP_BUFF_RXQ, 1,
+                         [struct xdp_buff has rxq])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
        AC_MSG_CHECKING([if firmware.h has request_firmware_direct])
        LB_LINUX_TRY_COMPILE([
                #include <linux/firmware.h>
@@ -3515,6 +3549,23 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
+       AC_MSG_CHECKING([if if_link.h has IFLA_VF_IB_NODE_PORT_GUID])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/if_link.h>
+       ],[
+               int type = IFLA_VF_IB_NODE_GUID;
+
+               type = IFLA_VF_IB_PORT_GUID;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_IFLA_VF_IB_NODE_PORT_GUID, 1,
+                         [trust is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
        AC_MSG_CHECKING([if skbuff.h skb_shared_info has UNION tx_flags])
        LB_LINUX_TRY_COMPILE([
                #include <linux/skbuff.h>
@@ -3666,6 +3717,21 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
+       AC_MSG_CHECKING([if net/tc_act/tc_mirred.h has tcf_mirred_dev])
+       LB_LINUX_TRY_COMPILE([
+               #include <net/tc_act/tc_mirred.h>
+       ],[
+               tcf_mirred_dev(NULL);
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TCF_MIRRED_DEV, 1,
+                         [tcf_mirred_dev is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
        AC_MSG_CHECKING([if enum tc_fl_command has TC_CLSFLOWER_STATS])
        LB_LINUX_TRY_COMPILE([
                #include <net/pkt_cls.h>
@@ -4475,7 +4541,24 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
-       AC_MSG_CHECKING([if mm has register_netdevice_notifier_rh])
+       AC_MSG_CHECKING([if netdevice.h has struct netdev_notifier_info])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct netdev_notifier_info x = {
+                       .dev = NULL,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NETDEV_NOTIFIER_INFO, 1,
+                         [struct netdev_notifier_info is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if netdevice.h has register_netdevice_notifier_rh])
        LB_LINUX_TRY_COMPILE([
        #include <linux/netdevice.h>
        ],[
@@ -4567,6 +4650,23 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
                AC_MSG_RESULT(no)
        ])
 
+       AC_MSG_CHECKING([if struct net_device_ops has ndo_change_mtu_rh74])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct net_device_ops netdev_ops = {
+                       .ndo_change_mtu_rh74 = NULL,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NDO_CHANGE_MTU_RH74, 1,
+                         [ndo_change_mtu_rh74 is defined in net_device_ops])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
        AC_MSG_CHECKING([if struct net_device_ops_extended has ndo_set_vf_vlan])
        LB_LINUX_TRY_COMPILE([
                #include <linux/netdevice.h>
@@ -5936,6 +6036,279 @@ AC_DEFUN([LINUX_CONFIG_COMPAT],
        ],[
                AC_MSG_RESULT(no)
        ])
+
+       AC_MSG_CHECKING([if skbuff.h has build_skb])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/skbuff.h>
+       ],[
+                build_skb(NULL, 0);
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BUILD_SKB, 1,
+                         [build_skb is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if include/net/devlink.h exists])
+       LB_LINUX_TRY_COMPILE([
+               #include <net/devlink.h>
+       ],[
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DEVLINK_H, 1,
+                         [include/net/devlink.h exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if net_device_ops_extended has ndo_get_phys_port_id])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+
+               int get_phys_port_name(struct net_device *dev,
+                                      char *name, size_t len)
+               {
+                       return 0;
+               }
+       ],[
+               struct net_device_ops_extended netdev_ops;
+
+               netdev_ops.ndo_get_phys_port_name = get_phys_port_name;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NDO_GET_PHYS_PORT_NAME_EXTENDED, 1,
+                         [ is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if struct net_device_ops ndo_vlan_rx_add_vid has 2 parameters and returns int])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+
+               int vlan_rx_add_vid(struct net_device *dev, u16 vid)
+               {
+                       return 0;
+               }
+       ],[
+               struct net_device_ops netdev_ops = {
+                       .ndo_vlan_rx_add_vid = vlan_rx_add_vid,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NDO_RX_ADD_VID_HAS_2_PARAMS_RET_INT, 1,
+                         [ndo_vlan_rx_add_vid has 2 parameters and returns int])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if netdev_extended has wanted_features])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct net_device *dev = NULL;
+
+               netdev_extended(dev)->wanted_features = 0;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NETDEV_EXTENDED_WANTED_FEATURES, 1,
+                         [ is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if netdevice.h has IFF_UNICAST_FLT])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               int x = IFF_UNICAST_FLT;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NETDEV_IFF_UNICAST_FLT, 1,
+                         [IFF_UNICAST_FLT is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if struct net_device has wanted_features])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct net_device dev;
+               dev.wanted_features = 0;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_NETDEV_WANTED_FEATURES, 1,
+                         [wanted_features is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if dcbnl.h has struct ieee_pfc])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+               #include <net/dcbnl.h>
+       ],[
+               struct ieee_pfc x;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_STRUCT_IEEE_PFC, 1,
+                         [ieee_pfc is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if struct tc_to_netdev has egress_dev])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct tc_to_netdev x = {
+                       .egress_dev = false,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TC_TO_NETDEV_EGRESS_DEV, 1,
+                         [struct tc_to_netdev has egress_dev])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if struct tc_to_netdev has tc])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               struct tc_to_netdev x;
+               x.tc = 0;
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TC_TO_NETDEV_TC, 1,
+                         [struct tc_to_netdev has tc])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if linux/bpf_trace has trace_xdp_exception])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/bpf_trace.h>
+       ],[
+               trace_xdp_exception(NULL, NULL, 0);
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_TRACE_XDP_EXCEPTION, 1,
+                         [trace_xdp_exception is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if filter.h has struct xdp_buff])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/filter.h>
+       ],[
+               struct xdp_buff d = {
+                       .data = NULL,
+                       .data_end = NULL,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XDP_BUFF, 1,
+                         [xdp is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if filter.h struct xdp_buff has data_hard_start])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/filter.h>
+       ],[
+               struct xdp_buff d = {
+                       .data_hard_start = NULL,
+               };
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XDP_BUFF_DATA_HARD_START, 1,
+                         [xdp_buff data_hard_start is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if filter.h has xdp_set_data_meta_invalid])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/filter.h>
+       ],[
+               struct xdp_buff d;
+               xdp_set_data_meta_invalid(&d);
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_XDP_SET_DATA_META_INVALID, 1,
+                         [xdp_set_data_meta_invalid is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if linux/bpf.h has bpf_prog_sub])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/bpf.h>
+       ],[
+               bpf_prog_sub(NULL, 0);
+
+               return 0;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_BPF_PROG_SUB, 1,
+                         [bpf_prog_sub is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       AC_MSG_CHECKING([if netdevice.h has enum netdev_lag_tx_type])
+       LB_LINUX_TRY_COMPILE([
+               #include <linux/netdevice.h>
+       ],[
+               enum netdev_lag_tx_type x;
+               x = 0;
+
+               return x;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_LAG_TX_TYPE, 1,
+                         [enum netdev_lag_tx_type is defined])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+
+       LB_CHECK_SYMBOL_EXPORT([bpf_prog_inc],
+               [kernel/bpf/syscall.c],
+               [AC_DEFINE(HAVE_BPF_PROG_INC_EXPORTED, 1,
+                       [bpf_prog_inc is exported by the kernel])],
+       [])
 ])
 #
 # COMPAT_CONFIG_HEADERS
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
new file mode 100644 (file)
index 0000000..b90db74
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _COMPAT_LINUX_BPF_H
+#define _COMPAT_LINUX_BPF_H
+
+#include "../../compat/config.h"
+
+#ifdef HAVE_LINUX_BPF_H
+#include_next <linux/bpf.h>
+
+#ifndef HAVE_BPF_PROG_INC_EXPORTED
+#define bpf_prog_inc LINUX_BACKPORT(bpf_prog_inc)
+static inline struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
+{
+       return bpf_prog_add(prog, 1);
+}
+#endif
+
+#ifndef HAVE_BPF_PROG_SUB
+#include <linux/filter.h>
+static inline void bpf_prog_sub(struct bpf_prog *prog, int i)
+{
+       /* Only to be used for undoing previous bpf_prog_add() in some
+        * error path. We still know that another entity in our call
+        * path holds a reference to the program, thus atomic_sub() can
+        * be safely used in such cases!
+        */
+       WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
+}
+#endif
+
+#endif /* HAVE_LINUX_BPF_H */
+
+#ifndef XDP_PACKET_HEADROOM
+#define XDP_PACKET_HEADROOM 256
+#endif
+
+#endif /* _COMPAT_LINUX_BPF_H */
index 028597a..a31f860 100644 (file)
@@ -55,6 +55,7 @@ void backport_dependency_symbol(void);
 #include <linux/compat-4.1.h>
 #include <linux/compat-4.5.h>
 #include <linux/compat-4.9.h>
+#include <linux/compat-4.17.h>
 
 #endif /* CONFIG_COMPAT_RDMA */
 #endif /* LINUX_26_COMPAT_H */
diff --git a/include/linux/compat-4.17.h b/include/linux/compat-4.17.h
new file mode 100644 (file)
index 0000000..63d4fd5
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef LINUX_4_17_COMPAT_H
+#define LINUX_4_17_COMPAT_H
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,17,0))
+
+#ifndef PFC_STORM_PREVENTION_AUTO
+#define PFC_STORM_PREVENTION_AUTO      0xffff
+#endif
+
+#ifndef PFC_STORM_PREVENTION_DISABLE
+#define PFC_STORM_PREVENTION_DISABLE   0
+#endif
+
+#include <linux/ethtool.h>
+#ifndef ETHTOOL_PFC_PREVENTION_TOUT
+#define ETHTOOL_PFC_PREVENTION_TOUT (ETHTOOL_TX_COPYBREAK + 1)
+#endif
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4,17,0)) */
+
+#endif /* LINUX_4_17_COMPAT_H */
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
new file mode 100644 (file)
index 0000000..987cbb6
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef LINUX_DCBNL_H
+#define LINUX_DCBNL_H
+
+#include "../../compat/config.h"
+
+#include_next <linux/dcbnl.h>
+
+#ifndef HAVE_IEEE_GETQCN
+
+#ifndef HAVE_STRUCT_IEEE_QCN
+enum dcbnl_cndd_states {
+       DCB_CNDD_RESET = 0,
+       DCB_CNDD_EDGE,
+       DCB_CNDD_INTERIOR,
+       DCB_CNDD_INTERIOR_READY,
+};
+
+struct ieee_qcn {
+       __u8 rpg_enable[IEEE_8021QAZ_MAX_TCS];
+       __u32 rppp_max_rps[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_time_reset[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_byte_reset[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_threshold[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_max_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_ai_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_hai_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_gd[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_min_dec_fac[IEEE_8021QAZ_MAX_TCS];
+       __u32 rpg_min_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 cndd_state_machine[IEEE_8021QAZ_MAX_TCS];
+};
+#endif /* HAVE_STRUCT_IEEE_QCN */
+
+/* RH7.3 backported this struct, but it does not have
+ * all needed feilds as below
+ * */
+#define ieee_qcn_stats mlnx_ofed_ieee_qcn_stats
+struct ieee_qcn_stats {
+       __u64 rppp_rp_centiseconds[IEEE_8021QAZ_MAX_TCS];
+       __u32 rppp_created_rps[IEEE_8021QAZ_MAX_TCS];
+       __u32 ignored_cnm[IEEE_8021QAZ_MAX_TCS];
+       __u32 estimated_total_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 cnms_handled_successfully[IEEE_8021QAZ_MAX_TCS];
+       __u32 min_total_limiters_rate[IEEE_8021QAZ_MAX_TCS];
+       __u32 max_total_limiters_rate[IEEE_8021QAZ_MAX_TCS];
+};
+
+#endif
+
+#ifndef IEEE_8021QAZ_APP_SEL_DSCP
+#define IEEE_8021QAZ_APP_SEL_DSCP      5
+#endif
+
+#ifndef HAVE_STRUCT_IEEE_PFC
+struct ieee_pfc {
+       __u8    pfc_cap;
+       __u8    pfc_en;
+       __u8    mbc;
+       __u16   delay;
+       __u64   requests[IEEE_8021QAZ_MAX_TCS];
+       __u64   indications[IEEE_8021QAZ_MAX_TCS];
+};
+#endif
+
+#endif /* LINUX_DCBNL_H */
diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h
new file mode 100644 (file)
index 0000000..29ed8fd
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017-2018, Broadcom Limited. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef NET_DIM_H
+#define NET_DIM_H
+
+#include <linux/module.h>
+
+struct net_dim_cq_moder {
+       u16 usec;
+       u16 pkts;
+       u8 cq_period_mode;
+};
+
+struct net_dim_sample {
+       ktime_t time;
+       u32     pkt_ctr;
+       u32     byte_ctr;
+       u16     event_ctr;
+};
+
+struct net_dim_stats {
+       int ppms; /* packets per msec */
+       int bpms; /* bytes per msec */
+       int epms; /* events per msec */
+};
+
+struct net_dim { /* Adaptive Moderation */
+       u8                                      state;
+       struct net_dim_stats                    prev_stats;
+       struct net_dim_sample                   start_sample;
+       struct work_struct                      work;
+       u8                                      profile_ix;
+       u8                                      mode;
+       u8                                      tune_state;
+       u8                                      steps_right;
+       u8                                      steps_left;
+       u8                                      tired;
+};
+
+enum {
+       NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0,
+       NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1,
+       NET_DIM_CQ_PERIOD_NUM_MODES
+};
+
+/* Adaptive moderation logic */
+enum {
+       NET_DIM_START_MEASURE,
+       NET_DIM_MEASURE_IN_PROGRESS,
+       NET_DIM_APPLY_NEW_PROFILE,
+};
+
+enum {
+       NET_DIM_PARKING_ON_TOP,
+       NET_DIM_PARKING_TIRED,
+       NET_DIM_GOING_RIGHT,
+       NET_DIM_GOING_LEFT,
+};
+
+enum {
+       NET_DIM_STATS_WORSE,
+       NET_DIM_STATS_SAME,
+       NET_DIM_STATS_BETTER,
+};
+
+enum {
+       NET_DIM_STEPPED,
+       NET_DIM_TOO_TIRED,
+       NET_DIM_ON_EDGE,
+};
+
+#define NET_DIM_PARAMS_NUM_PROFILES 5
+/* Adaptive moderation profiles */
+#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
+#define NET_DIM_DEF_PROFILE_CQE 1
+#define NET_DIM_DEF_PROFILE_EQE 1
+
+/* All profiles sizes must be NET_PARAMS_DIM_NUM_PROFILES */
+#define NET_DIM_EQE_PROFILES { \
+       {1,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {8,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {64,  NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+}
+
+#define NET_DIM_CQE_PROFILES { \
+       {2,  256},             \
+       {8,  128},             \
+       {16, 64},              \
+       {32, 64},              \
+       {64, 64}               \
+}
+
+static const struct net_dim_cq_moder
+profile[NET_DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+       NET_DIM_EQE_PROFILES,
+       NET_DIM_CQE_PROFILES,
+};
+
+static inline struct net_dim_cq_moder net_dim_get_profile(u8 cq_period_mode,
+                                                         int ix)
+{
+       struct net_dim_cq_moder cq_moder;
+
+       cq_moder = profile[cq_period_mode][ix];
+       cq_moder.cq_period_mode = cq_period_mode;
+       return cq_moder;
+}
+
+static inline struct net_dim_cq_moder net_dim_get_def_profile(u8 rx_cq_period_mode)
+{
+       int default_profile_ix;
+
+       if (rx_cq_period_mode == NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE)
+               default_profile_ix = NET_DIM_DEF_PROFILE_CQE;
+       else /* NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE */
+               default_profile_ix = NET_DIM_DEF_PROFILE_EQE;
+
+       return net_dim_get_profile(rx_cq_period_mode, default_profile_ix);
+}
+
+static inline bool net_dim_on_top(struct net_dim *dim)
+{
+       switch (dim->tune_state) {
+       case NET_DIM_PARKING_ON_TOP:
+       case NET_DIM_PARKING_TIRED:
+               return true;
+       case NET_DIM_GOING_RIGHT:
+               return (dim->steps_left > 1) && (dim->steps_right == 1);
+       default: /* NET_DIM_GOING_LEFT */
+               return (dim->steps_right > 1) && (dim->steps_left == 1);
+       }
+}
+
+static inline void net_dim_turn(struct net_dim *dim)
+{
+       switch (dim->tune_state) {
+       case NET_DIM_PARKING_ON_TOP:
+       case NET_DIM_PARKING_TIRED:
+               break;
+       case NET_DIM_GOING_RIGHT:
+               dim->tune_state = NET_DIM_GOING_LEFT;
+               dim->steps_left = 0;
+               break;
+       case NET_DIM_GOING_LEFT:
+               dim->tune_state = NET_DIM_GOING_RIGHT;
+               dim->steps_right = 0;
+               break;
+       }
+}
+
+static inline int net_dim_step(struct net_dim *dim)
+{
+       if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2))
+               return NET_DIM_TOO_TIRED;
+
+       switch (dim->tune_state) {
+       case NET_DIM_PARKING_ON_TOP:
+       case NET_DIM_PARKING_TIRED:
+               break;
+       case NET_DIM_GOING_RIGHT:
+               if (dim->profile_ix == (NET_DIM_PARAMS_NUM_PROFILES - 1))
+                       return NET_DIM_ON_EDGE;
+               dim->profile_ix++;
+               dim->steps_right++;
+               break;
+       case NET_DIM_GOING_LEFT:
+               if (dim->profile_ix == 0)
+                       return NET_DIM_ON_EDGE;
+               dim->profile_ix--;
+               dim->steps_left++;
+               break;
+       }
+
+       dim->tired++;
+       return NET_DIM_STEPPED;
+}
+
+static inline void net_dim_park_on_top(struct net_dim *dim)
+{
+       dim->steps_right  = 0;
+       dim->steps_left   = 0;
+       dim->tired        = 0;
+       dim->tune_state   = NET_DIM_PARKING_ON_TOP;
+}
+
+static inline void net_dim_park_tired(struct net_dim *dim)
+{
+       dim->steps_right  = 0;
+       dim->steps_left   = 0;
+       dim->tune_state   = NET_DIM_PARKING_TIRED;
+}
+
+static inline void net_dim_exit_parking(struct net_dim *dim)
+{
+       dim->tune_state = dim->profile_ix ? NET_DIM_GOING_LEFT :
+                                         NET_DIM_GOING_RIGHT;
+       net_dim_step(dim);
+}
+
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+       (((100UL * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
+static inline int net_dim_stats_compare(struct net_dim_stats *curr,
+                                       struct net_dim_stats *prev)
+{
+       if (!prev->bpms)
+               return curr->bpms ? NET_DIM_STATS_BETTER :
+                                   NET_DIM_STATS_SAME;
+
+       if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+               return (curr->bpms > prev->bpms) ? NET_DIM_STATS_BETTER :
+                                                  NET_DIM_STATS_WORSE;
+
+       if (!prev->ppms)
+               return curr->ppms ? NET_DIM_STATS_BETTER :
+                                   NET_DIM_STATS_SAME;
+
+       if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+               return (curr->ppms > prev->ppms) ? NET_DIM_STATS_BETTER :
+                                                  NET_DIM_STATS_WORSE;
+
+       if (!prev->epms)
+               return NET_DIM_STATS_SAME;
+
+       if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+               return (curr->epms < prev->epms) ? NET_DIM_STATS_BETTER :
+                                                  NET_DIM_STATS_WORSE;
+
+       return NET_DIM_STATS_SAME;
+}
+
+static inline bool net_dim_decision(struct net_dim_stats *curr_stats,
+                                   struct net_dim *dim)
+{
+       int prev_state = dim->tune_state;
+       int prev_ix = dim->profile_ix;
+       int stats_res;
+       int step_res;
+
+       switch (dim->tune_state) {
+       case NET_DIM_PARKING_ON_TOP:
+               stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats);
+               if (stats_res != NET_DIM_STATS_SAME)
+                       net_dim_exit_parking(dim);
+               break;
+
+       case NET_DIM_PARKING_TIRED:
+               dim->tired--;
+               if (!dim->tired)
+                       net_dim_exit_parking(dim);
+               break;
+
+       case NET_DIM_GOING_RIGHT:
+       case NET_DIM_GOING_LEFT:
+               stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats);
+               if (stats_res != NET_DIM_STATS_BETTER)
+                       net_dim_turn(dim);
+
+               if (net_dim_on_top(dim)) {
+                       net_dim_park_on_top(dim);
+                       break;
+               }
+
+               step_res = net_dim_step(dim);
+               switch (step_res) {
+               case NET_DIM_ON_EDGE:
+                       net_dim_park_on_top(dim);
+                       break;
+               case NET_DIM_TOO_TIRED:
+                       net_dim_park_tired(dim);
+                       break;
+               }
+
+               break;
+       }
+
+       if ((prev_state      != NET_DIM_PARKING_ON_TOP) ||
+           (dim->tune_state != NET_DIM_PARKING_ON_TOP))
+               dim->prev_stats = *curr_stats;
+
+       return dim->profile_ix != prev_ix;
+}
+
+static inline void net_dim_sample(u16 event_ctr,
+                                 u64 packets,
+                                 u64 bytes,
+                                 struct net_dim_sample *s)
+{
+       s->time      = ktime_get();
+       s->pkt_ctr   = packets;
+       s->byte_ctr  = bytes;
+       s->event_ctr = event_ctr;
+}
+
+#define NET_DIM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
+
+static inline void net_dim_calc_stats(struct net_dim_sample *start,
+                                     struct net_dim_sample *end,
+                                     struct net_dim_stats *curr_stats)
+{
+       /* u32 holds up to 71 minutes, should be enough */
+       u32 delta_us = ktime_us_delta(end->time, start->time);
+       u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+       u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+                            start->byte_ctr);
+
+       if (!delta_us)
+               return;
+
+       curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+       curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+       curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC,
+                                       delta_us);
+}
+
+static inline void net_dim(struct net_dim *dim,
+                          struct net_dim_sample end_sample)
+{
+       struct net_dim_stats curr_stats;
+       u16 nevents;
+
+       switch (dim->state) {
+       case NET_DIM_MEASURE_IN_PROGRESS:
+               nevents = BIT_GAP(BITS_PER_TYPE(u16),
+                                 end_sample.event_ctr,
+                                 dim->start_sample.event_ctr);
+               if (nevents < NET_DIM_NEVENTS)
+                       break;
+               net_dim_calc_stats(&dim->start_sample, &end_sample,
+                                  &curr_stats);
+               if (net_dim_decision(&curr_stats, dim)) {
+                       dim->state = NET_DIM_APPLY_NEW_PROFILE;
+                       schedule_work(&dim->work);
+                       break;
+               }
+               /* fall through */
+       case NET_DIM_START_MEASURE:
+               dim->state = NET_DIM_MEASURE_IN_PROGRESS;
+               break;
+       case NET_DIM_APPLY_NEW_PROFILE:
+               break;
+       }
+}
+
+#endif /* NET_DIM_H */
index 6332329..4de00eb 100644 (file)
 #define ndo_bpf                ndo_xdp
 #endif
 
+static inline const char *netdev_reg_state(const struct net_device *dev)
+{
+       switch (dev->reg_state) {
+       case NETREG_UNINITIALIZED: return " (uninitialized)";
+       case NETREG_REGISTERED: return "";
+       case NETREG_UNREGISTERING: return " (unregistering)";
+       case NETREG_UNREGISTERED: return " (unregistered)";
+       case NETREG_RELEASED: return " (released)";
+       case NETREG_DUMMY: return " (dummy)";
+       }
+
+       WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, dev->reg_state);
+       return " (unknown)";
+}
+
 #ifndef HAVE_TC_SETUP_QDISC_MQPRIO
 #define TC_SETUP_QDISC_MQPRIO TC_SETUP_MQPRIO
 
@@ -47,9 +62,10 @@ do {                                                         \
        netdev_level_once(KERN_INFO, dev, fmt, ##__VA_ARGS__)
 
 
-#define netdev_WARN_ONCE(dev, condition, format, arg...)               \
-       WARN_ONCE(1, "netdevice: %s%s\n" format, netdev_name(dev)       \
+#define netdev_WARN_ONCE(dev, format, args...)                         \
+       WARN_ONCE(1, "netdevice: %s%s: " format, netdev_name(dev),      \
                  netdev_reg_state(dev), ##args)
+
 #endif /* netdev_WARN_ONCE */
 #endif