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>
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>
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>
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>
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>
],[
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>
],[
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
--- /dev/null
+#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 */
#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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 */
#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
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