diff --git a/Makefile b/Makefile index 8d8e0fc..6717776 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Copyright (C) 2021 Intel Corporation TARGETS := idpf auxiliary -VERSION := 1.0.2 +VERSION := 1.0.6 # Shortcut version target ifneq ($(filter version,${MAKECMDGOALS}),) @@ -19,6 +19,18 @@ ifneq (${KERNELRELEASE},) obj-y := $(strip $(addsuffix /src/,${TARGETS})) ccflags-y += -I$(src) subdir-ccflags-y += -I$(src) + +# Apply build modifier flags +ifeq (${BUILD_UPLINK_PORT_STATS},YES) + ccflags-y += -DCONFIG_UPLINK_PORT_STATS + subdir-ccflags-y += -DCONFIG_UPLINK_PORT_STATS +endif + +ifeq (${BUILD_RCA},YES) + ccflags-y += -DCONFIG_RCA_SUPPORT -DCONFIG_OEM_CAPS + subdir-ccflags-y += -DCONFIG_RCA_SUPPORT -DCONFIG_OEM_CAPS +endif + else # ifneq (${KERNELRELEASE},) # normal make @@ -68,12 +80,12 @@ endif CHECK_AUX_BUS := $(realpath ./scripts/check_aux_bus) $(shell chmod +x ${CHECK_AUX_BUS}) -include common.mk +include idpf/src/common.mk # SIOV support is only supported if the kernel has features for controlling # PASID support. Do not even try to build SIOV support if the kernel lacks # the necessary infrastructure. -ifneq ($(shell grep HAVE_PASID_SUPPORT $(src)/kcompat_generated_defs.h),) +ifneq ($(shell grep HAVE_PASID_SUPPORT idpf/src/kcompat_generated_defs.h),) export ENABLE_SIOV_SUPPORT := 1 else # Force SIOV support on ARM, which is needed by ACC. Since we cannot @@ -84,7 +96,7 @@ export ENABLE_SIOV_SUPPORT := 1 override CFLAGS_EXTRA += -DENABLE_ACC_PASID_WA endif endif # HAVE_PASID_SUPPORT is in kcompat_generated_defs.h -ifneq ($(shell grep HAVE_DEVLINK_PORT_NEW $(src)/kcompat_generated_defs.h),) +ifneq ($(shell grep HAVE_DEVLINK_PORT_NEW idpf/src/kcompat_generated_defs.h),) export ENABLE_DEVLINK_SUPPORT := 1 endif # HAVE_DEVLINK_PORT_NEW is in kcompat_generated_defs.h @@ -137,9 +149,26 @@ $(call cmd_depmod) endef endif -compile: +# Set default goal to compile (must be set before the first target is defined) +.DEFAULT_GOAL := compile + +# Ensure kcompat_generated_defs.h exists for all targets before compiling +# This is done by invoking a simple target in each module's Makefile which +# will cause common.mk to be included and generate the kcompat file +.PHONY: prepare_kcompat +prepare_kcompat: + @for target in ${TARGETS}; do \ + if [ -f $$target/src/Makefile ]; then \ + ${MAKE} -C $$target/src --no-print-directory -s version 2>/dev/null || true; \ + fi; \ + done + +compile: prepare_kcompat @${MAKE} -C ${KSRC} M=$$PWD ${CONFIG_DRIVERS} ccflags-y="${CFLAGS_EXTRA} ${EXTRA_CFLAGS}" modules \ - NEED_AUX_BUS=${NEED_AUX_BUS} ${EXTRA_OPTS} + NEED_AUX_BUS=${NEED_AUX_BUS} \ + BUILD_UPLINK_PORT_STATS=${BUILD_UPLINK_PORT_STATS} \ + BUILD_RCA=${BUILD_RCA} \ + ${EXTRA_OPTS} .PHONY: install install: compile @@ -155,7 +184,7 @@ uninstall: .PHONY: clean clean: @${MAKE} -C ${KSRC} M=$$PWD clean - @rm -f kcompat_generated_defs.h + @rm -f idpf/src/kcompat_generated_defs.h auxiliary/src/kcompat_generated_defs.h endif # ifneq (${KERNELRELEASE},) endif # version target handling diff --git a/auxiliary/src/common.mk b/auxiliary/src/common.mk index 90de464..5454c54 100644 --- a/auxiliary/src/common.mk +++ b/auxiliary/src/common.mk @@ -347,8 +347,8 @@ ifeq (,${MANDIR}) MANDIR := $(firstword ${MANDIR}) endif ifeq (,${MANDIR}) - # fallback to /usr/man - MANDIR := /usr/man + # fallback to /usr/share/man (FHS standard; legacy /usr/man not present on RHEL 9+) + MANDIR := /usr/share/man endif #################### diff --git a/auxiliary/src/kcompat-generator.sh b/auxiliary/src/kcompat-generator.sh index 068c7ec..556aba8 100644 --- a/auxiliary/src/kcompat-generator.sh +++ b/auxiliary/src/kcompat-generator.sh @@ -83,7 +83,11 @@ function gen-cleanup() { rcuh='include/linux/rcupdate.h' gen NEED_DEFINE_FREE if macro DEFINE_FREE absent in "$ch" gen NEED___DEFINE_CLASS_IS_CONDITIONAL if macro __DEFINE_CLASS_IS_CONDITIONAL absent in "$ch" - gen NEED_DEFINE_GUARD_MUTEX if invocation of macro DEFINE_GUARD absent or lacks mutex_lock in "$mh" + # Check for mutex guards in both old and new APIs + HAVE_MUTEX_GUARDS=0 + check invocation of macro DEFINE_LOCK_GUARD_1 matches mutex in "$mh" && HAVE_MUTEX_GUARDS=1 + check invocation of macro DEFINE_GUARD matches mutex in "$mh" && HAVE_MUTEX_GUARDS=1 + gen NEED_DEFINE_GUARD_MUTEX if string "$HAVE_MUTEX_GUARDS" equals 0 gen NEED_LOCK_GUARD_FOR_RCU if invocation of macro DEFINE_LOCK_GUARD_0 absent or lacks rcu in "$rcuh" gen NEED_DEFINE_FREE_KFREE if invocation of macro DEFINE_FREE absent or lacks kfree in "$slabh" gen NEED_DEFINE_FREE_KVFREE if invocation of macro DEFINE_FREE absent or lacks kvfree in "$slabh" @@ -183,6 +187,7 @@ function gen-dpll() { gen HAVE_DPLL_PHASE_OFFSET if method phase_offset_get of dpll_pin_ops in "$dh" gen HAVE_DPLL_PHASE_OFFSET_MONITOR if method phase_offset_monitor_set of dpll_device_ops in "$dh" gen NEED_DPLL_NETDEV_PIN_SET if fun dpll_netdev_pin_set absent in "$dh" + gen NEED_DPLL_TRACKER if typedef dpll_tracker absent in "$dh" } function gen-ethtool() { @@ -379,7 +384,10 @@ function gen-packing() { } function gen-pci() { + ioporth='include/linux/ioport.h' pcih='include/linux/pci.h' + gen HAVE_RESOURCE_SET_RANGE if fun resource_set_range in "$ioporth" + gen HAVE_RESOURCE_SET_SIZE if fun resource_set_size in "$ioporth" gen HAVE_PCI_MSIX_ALLOC_IRQ_AT if fun pci_msix_alloc_irq_at in "$pcih" gen HAVE_PCI_MSIX_CAN_ALLOC_DYN if fun pci_msix_can_alloc_dyn in "$pcih" gen HAVE_PCI_MSIX_FREE_IRQ if fun pci_msix_free_irq in "$pcih" @@ -404,6 +412,7 @@ function gen-ptp() { gen HAVE_PTP_CANCEL_WORKER_SYNC if fun ptp_cancel_worker_sync in "$clockh" gen HAVE_PTP_CLOCK_DO_AUX_WORK if method do_aux_work of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_ADJFINE if method adjfine of ptp_clock_info in "$clockh" + gen HAVE_PTP_CLOCK_INFO_GETCYCLES64 if method getcycles64 of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_GETTIME64 if method gettime64 of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_GETTIMEX64 if method gettimex64 of ptp_clock_info in "$clockh" gen HAVE_PTP_FIND_PIN_UNLOCKED if fun ptp_find_pin_unlocked in "$clockh" @@ -525,8 +534,9 @@ function gen-other() { gen HAVE_MDEV_GET_DRVDATA if fun mdev_get_drvdata in include/linux/mdev.h gen HAVE_MDEV_REGISTER_PARENT if fun mdev_register_parent in include/linux/mdev.h gen HAVE_VM_FLAGS_API if fun vm_flags_init in include/linux/mm.h + gen NEED_MODULE_INFO_WITHOUT_CHECK if implementation of macro MODULE_INFO matches __builtin_strlen in include/linux/moduleparam.h gen HAVE_NL_SET_ERR_MSG_FMT if macro NL_SET_ERR_MSG_FMT in include/linux/netlink.h - gen NEED_DEFINE_SIMPLE_DEV_OPS if macro DEFINE_SIMPLE_DEV_OPS absent in include/linux/pm.h + gen NEED_DEFINE_SIMPLE_DEV_PM_OPS if macro DEFINE_SIMPLE_DEV_PM_OPS absent in include/linux/pm.h gen NEED_PM_SLEEP_PTR if macro pm_sleep_ptr absent in include/linux/pm.h gen NEED_DEV_PM_DOMAIN_ATTACH if fun dev_pm_domain_attach absent in include/linux/pm_domain.h include/linux/pm.h gen NEED_DEV_PM_DOMAIN_DETACH if fun dev_pm_domain_detach absent in include/linux/pm_domain.h include/linux/pm.h diff --git a/auxiliary/src/kcompat.c b/auxiliary/src/kcompat.c index 3c4e524..fb20942 100644 --- a/auxiliary/src/kcompat.c +++ b/auxiliary/src/kcompat.c @@ -2697,3 +2697,37 @@ void pci_disable_ptm(struct pci_dev *dev) #endif /* HAVE_STRUCT_PCI_DEV_PTM_ENABLED && CONFIG_PCIE_PTM */ } #endif /* NEED_PCI_DISABLE_PTM */ + +#ifndef HAVE_RESOURCE_SET_SIZE +/** + * resource_set_size - Calculate resource end address from size and start + * @res: Resource descriptor + * @size: Size of the resource + * + * Calculate the end address for @res based on @size. + * + * Note: The start address of @res must be set when calling this function. + * Prefer resource_set_range() if setting both the start address and @size. + */ +void resource_set_size(struct resource *res, resource_size_t size) +{ + res->end = res->start + size - 1; +} +#endif /* !HAVE_RESOURCE_SET_SIZE */ + +#ifndef HAVE_RESOURCE_SET_RANGE +/** + * resource_set_range - Set resource start and end addresses + * @res: Resource descriptor + * @start: Start address for the resource + * @size: Size of the resource + * + * Set @res start address and calculate the end address based on @size. + */ +void resource_set_range(struct resource *res, resource_size_t start, + resource_size_t size) +{ + res->start = start; + resource_set_size(res, size); +} +#endif /* !HAVE_RESOURCE_SET_RANGE */ diff --git a/auxiliary/src/kcompat.h b/auxiliary/src/kcompat.h index 6a2d15d..0c1d918 100644 --- a/auxiliary/src/kcompat.h +++ b/auxiliary/src/kcompat.h @@ -58,7 +58,7 @@ /* any of the features that need to alter module_init */ #if !defined(HAVE_XARRAY_API) -static int __init kc_module_init_impl(void) +static inline int __init kc_module_init_impl(void) { #ifdef HAVE_XARRAY_API #else diff --git a/auxiliary/src/kcompat_impl.h b/auxiliary/src/kcompat_impl.h index 2d2132e..273c327 100644 --- a/auxiliary/src/kcompat_impl.h +++ b/auxiliary/src/kcompat_impl.h @@ -3414,6 +3414,18 @@ enum dpll_lock_status_error { #define dpll_netdev_pin_clear netdev_dpll_pin_clear #endif /* NEED_DPLL_NETDEV_PIN_SET */ +#ifdef NEED_DPLL_TRACKER +#ifdef CONFIG_DPLL +#include +#define dpll_device_get(clock_id, device_idx, module, tracker) \ + dpll_device_get(clock_id, device_idx, module) +#define dpll_device_put(dpll, tracker) dpll_device_put(dpll) +#define dpll_pin_get(clock_id, pin_idx, module, prop, tracker) \ + dpll_pin_get(clock_id, pin_idx, module, prop) +#define dpll_pin_put(pin, tracker) dpll_pin_put(pin) +#endif /* CONFIG_DPLL */ +#endif /* NEED_DPLL_TRACKER */ + #ifdef NEED_RADIX_TREE_EMPTY static inline bool radix_tree_empty(struct radix_tree_root *root) { @@ -3626,12 +3638,36 @@ void _kc_eventfd_signal(struct eventfd_ctx *ctx) #define TCP_MIN_MSS 88U #endif -#ifdef NEED_DEFINE_SIMPLE_DEV_OPS -#define DEFINE_SIMPLE_DEV_OPS(name, suspend_fn, resume_fn) \ +#ifdef NEED_DEFINE_SIMPLE_DEV_PM_OPS +#define DEFINE_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) -#endif /* NEED_DEFINE_SIMPLE_DEV_OPS */ +#endif /* NEED_DEFINE_SIMPLE_DEV_PM_OPS */ #ifdef NEED_PM_SLEEP_PTR #define pm_sleep_ptr(_ptr) (_ptr) #endif /* NEED_PM_SLEEP_PTR */ + +#ifdef NEED_MODULE_INFO_WITHOUT_CHECK +/* upstream commit ae83f3b72621 ("module: Add compile-time check for embedded + * NUL characters") added an assert preventing embedding dishonest licenses, + * like "GPL\0, but proprietary for XXX part". Unfortunately __builtin_strlen() + * used does not work in some of our CI builds, so just remove that (essentially + * "reverting" the upstream commit). + */ +#include +#undef MODULE_INFO +#define MODULE_INFO(tag, info) \ + static const char __UNIQUE_ID(modinfo)[] \ + __used __section(".modinfo") __aligned(1) \ + = __MODULE_INFO_PREFIX __stringify(tag) "=" info +#endif /* NEED_MODULE_INFO_WITHOUT_CHECK */ + +#ifndef HAVE_RESOURCE_SET_SIZE +void resource_set_size(struct resource *res, resource_size_t size); +#endif /* !HAVE_RESOURCE_SET_SIZE */ +#ifndef HAVE_RESOURCE_SET_RANGE +void resource_set_range(struct resource *res, resource_size_t start, + resource_size_t size); +#endif /* !HAVE_RESOURCE_SET_RANGE */ + #endif /* _KCOMPAT_IMPL_H_ */ diff --git a/common.mk b/common.mk deleted file mode 100644 index 90de464..0000000 --- a/common.mk +++ /dev/null @@ -1,463 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Copyright (C) 2019-2025 Intel Corporation - -# -# common Makefile rules useful for out-of-tree Linux driver builds -# -# Usage: include common.mk -# -# After including, you probably want to add a minimum_kver_check call -# -# Required Variables: -# DRIVER -# -- Set to the lowercase driver name - -##################### -# Helpful functions # -##################### - -SHELL := $(shell which bash) -src ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -readlink = $(shell readlink -f ${1}) - -# helper functions for converting kernel version to version codes -get_kver = $(or $(word ${2},$(subst ., ,${1})),0) -get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \ - [ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \ - [ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \ - printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) ) - -################ -# depmod Macro # -################ - -cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \ - $(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \ - -a ${KVER} - -##################### -# Environment tests # -##################### - -DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]") - -ifeq (,${BUILD_KERNEL}) -BUILD_KERNEL=$(shell uname -r) -endif - -# Kernel Search Path -# All the places we look for kernel source -KSP := /lib/modules/${BUILD_KERNEL}/source \ - /lib/modules/${BUILD_KERNEL}/build \ - /usr/src/linux-${BUILD_KERNEL} \ - /usr/src/kernel-headers-${BUILD_KERNEL} \ - /usr/src/kernel-source-${BUILD_KERNEL} \ - /usr/src/linux \ - /usr/src/kernels/${BUILD_KERNEL} \ - /usr/src/kernels - -# prune the list down to only values that exist and have an include/linux -# sub-directory. We can't use include/config because some older kernels don't -# have this. -test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir}) -KSP := $(foreach dir, ${KSP}, ${test_dir}) - -# we will use this first valid entry in the search path -ifeq (,${KSRC}) - KSRC := $(firstword ${KSP}) -endif - -ifeq (,${KSRC}) - $(warning *** Kernel header files not in any of the expected locations.) - $(warning *** Install the appropriate kernel development package, e.g.) - $(error kernel-devel, for building kernel modules and try again) -else -ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC}) - KOBJ := /lib/modules/${BUILD_KERNEL}/build -else - KOBJ := ${KSRC} -endif -endif - -SCRIPT_PATH := ${KSRC}/scripts -info_signed_modules = - -ifeq (,${SCRIPT_PATH}) - info_signed_modules += echo "*** Could not find sign-file script. Cannot sign driver." ; -else - SIGN_FILE_EXISTS := $(or $(and $(wildcard $(SCRIPT_PATH)/sign-file),1),) - PRIV_KEY_EXISTS := $(or $(and $(wildcard intel-linux-key.key),1),) - PUB_KEY_EXISTS := $(or $(and $(wildcard intel-linux-key.crt),1),) -ifneq ($(and $(SIGN_FILE_EXISTS),$(PRIV_KEY_EXISTS),$(PUB_KEY_EXISTS)),) - info_signed_modules += \ - echo "*** Is sign-file present: ${SIGN_FILE_EXISTS}" ; \ - echo "*** Is private key present: ${PRIV_KEY_EXISTS}" ; \ - echo "*** Is public key present: ${PUB_KEY_EXISTS}" ; - info_signed_modules += echo "*** All files are present, signing driver." ; - sign_driver = $(shell ${SCRIPT_PATH}/sign-file sha256 intel-linux-key.key \ - intel-linux-key.crt ${DRIVER}.ko) -else - info_signed_modules += echo "*** Files are missing, cannot sign driver." ; - sign_driver = -endif -endif - -# Version file Search Path -VSP := ${KOBJ}/include/generated/utsrelease.h \ - ${KOBJ}/include/linux/utsrelease.h \ - ${KOBJ}/include/linux/version.h \ - ${KOBJ}/include/generated/uapi/linux/version.h \ - /boot/vmlinuz.version.h - -# Config file Search Path -CSP := ${KOBJ}/include/generated/autoconf.h \ - ${KOBJ}/include/linux/autoconf.h \ - /boot/vmlinuz.autoconf.h - -# System.map Search Path (for depmod) -MSP := ${KSRC}/System.map \ - /usr/lib/debug/boot/System.map-${BUILD_KERNEL} \ - /boot/System.map-${BUILD_KERNEL} - -# prune the lists down to only files that exist -test_file = $(shell [ -f ${1} ] && echo ${1}) -VSP := $(foreach file, ${VSP}, $(call test_file,${file})) -CSP := $(foreach file, ${CSP}, $(call test_file,${file})) -MSP := $(foreach file, ${MSP}, $(call test_file,${file})) - - -# and use the first valid entry in the Search Paths -ifeq (,${VERSION_FILE}) - VERSION_FILE := $(firstword ${VSP}) -endif - -ifeq (,${CONFIG_FILE}) - CONFIG_FILE := $(firstword ${CSP}) -endif - -ifeq (,${SYSTEM_MAP_FILE}) - SYSTEM_MAP_FILE := $(firstword ${MSP}) -endif - -ifeq (,$(wildcard ${VERSION_FILE})) - $(error Linux kernel source not configured - missing version header file) -endif - -ifeq (,$(wildcard ${CONFIG_FILE})) - $(error Linux kernel source not configured - missing autoconf.h) -endif - -ifeq (,$(wildcard ${SYSTEM_MAP_FILE})) - $(warning Missing System.map file - depmod will not check for missing symbols during module installation) -endif - -ifneq ($(words $(subst :, ,$(CURDIR))), 1) - $(error Sources directory '$(CURDIR)' cannot contain spaces nor colons. Rename directory or move sources to another path) -endif - -######################## -# Extract config value # -######################## - -get_config_value = $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ - grep -m 1 ${1} | awk '{ print $$3 }') - -################ -# dracut Macro # -################ - -cmd_initrd := $(shell \ - if [[ ${KOBJ} != /lib/modules/${BUILD_KERNEL}/* ]]; then \ - echo ""; \ - elif which dracut > /dev/null 2>&1 ; then \ - echo "dracut --force --kver ${BUILD_KERNEL}"; \ - elif which update-initramfs > /dev/null 2>&1 ; then \ - echo "update-initramfs -u -k ${BUILD_KERNEL}"; \ - fi ) - -######################## -# Check module signing # -######################## - -CONFIG_MODULE_SIG_ALL := $(call get_config_value,CONFIG_MODULE_SIG_ALL) -CONFIG_MODULE_SIG_FORCE := $(call get_config_value,CONFIG_MODULE_SIG_FORCE) -CONFIG_MODULE_SIG_KEY := $(call get_config_value,CONFIG_MODULE_SIG_KEY) - -SIG_KEY_SP := ${KOBJ}/${CONFIG_MODULE_SIG_KEY} \ - ${KOBJ}/certs/signing_key.pem - -SIG_KEY_FILE := $(firstword $(foreach file, ${SIG_KEY_SP}, $(call test_file,${file}))) - -# print a warning if the kernel configuration attempts to sign modules but -# the signing key can't be found. -ifneq (${SIG_KEY_FILE},) -warn_signed_modules := : ; -else -warn_signed_modules := -ifeq (${CONFIG_MODULE_SIG_ALL},1) -warn_signed_modules += \ - echo "*** The target kernel has CONFIG_MODULE_SIG_ALL enabled, but" ; \ - echo "*** the signing key cannot be found. Module signing has been" ; \ - echo "*** disabled for this build." ; -endif # CONFIG_MODULE_SIG_ALL=y -ifeq (${CONFIG_MODULE_SIG_FORCE},1) - warn_signed_modules += \ - echo "warning: The target kernel has CONFIG_MODULE_SIG_FORCE enabled," ; \ - echo "warning: but the signing key cannot be found. The module must" ; \ - echo "warning: be signed manually using 'scripts/sign-file'." ; -endif # CONFIG_MODULE_SIG_FORCE -DISABLE_MODULE_SIGNING := Yes -endif - -####################### -# Linux Version Setup # -####################### - -# The following command line parameter is intended for development of KCOMPAT -# against upstream kernels such as net-next which have broken or non-updated -# version codes in their Makefile. They are intended for debugging and -# development purpose only so that we can easily test new KCOMPAT early. If you -# don't know what this means, you do not need to set this flag. There is no -# arcane magic here. - -# Convert LINUX_VERSION into LINUX_VERSION_CODE -ifneq (${LINUX_VERSION},) - LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3)) -endif - -# Honor LINUX_VERSION_CODE -ifneq (${LINUX_VERSION_CODE},) - $(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.) - KVER_CODE := ${LINUX_VERSION_CODE} - EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE} -endif - -# Determine SLE_KERNEL_REVISION for SuSE SLE >= 11 (needed by kcompat) -# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string -# appended to the stable kernel version on which their kernel is based with -# additional versioning information (up to 3 numbers), a possible abbreviated -# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default -# or CONFIG_LOCALVERSION=-999.gdeadbee-default -# SLE >= 15SP3 added additional information about version and service pack -# to their kernel version e.g CONFIG_LOCALVERSION=-150300.59.43.1-default -# -# SLE_LOCALVERSION_CODE is also exported to support legacy kcompat.h -# definitions. -ifeq (1,$(call get_config_value,CONFIG_SUSE_KERNEL)) - -ifneq (10,$(call get_config_value,CONFIG_SLE_VERSION)) - - CONFIG_LOCALVERSION := $(call get_config_value,CONFIG_LOCALVERSION) - LOCALVERSION := $(shell echo ${CONFIG_LOCALVERSION} | \ - cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//') - LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1) -ifeq ($(shell test ${LOCALVER_A} -gt 65535; echo $$?),0) - LOCAL_VER_MAJOR := $(shell echo ${LOCALVER_A:0:3}) - LOCAL_VER_MINOR := $(shell echo ${LOCALVER_A:3:3}) - LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) - LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) - LOCALVER_D := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f4) - SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_B} \* 65536 + \ - 0${LOCALVER_C} \* 256 + 0${LOCALVER_D}) - EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} - EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_B} -else - LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) - LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) - SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \ - 0${LOCALVER_B} \* 256 + 0${LOCALVER_C}) - EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} - EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_A} -endif -endif -endif - -EXTRA_CFLAGS += -std=gnu11 -EXTRA_CFLAGS += ${CFLAGS_EXTRA} - -# get the kernel version - we use this to find the correct install path -KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \ - awk '{ print $$3 }' | sed 's/\"//g') - -# assume source symlink is the same as build, otherwise adjust KOBJ -ifneq (,$(wildcard /lib/modules/${KVER}/build)) - ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build)) - KOBJ=/lib/modules/${KVER}/build - endif -endif - -ifeq (${KVER_CODE},) - KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\ - grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g') -endif - -# minimum_kver_check -# -# helper function to provide uniform output for different drivers to abort the -# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)". -define _minimum_kver_check -ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?")) - $$(warning *** Aborting the build.) - $$(error This driver is not supported on kernel versions older than ${1}.${2}.${3}) -endif -endef -minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3})) - -############################# -# kcompat definitions setup # -############################# - -# In most cases, kcompat flags can be checked within the driver source files -# using simple CPP checks. However, it may be necessary to check for a flag -# value within the Makefile for some specific edge cases. For example, if an -# entire feature ought to be excluded on some kernels due to missing -# functionality. -# -# To support this, kcompat_defs.h is preprocessed and converted into a word list -# that can be checked to determine whether a given kcompat feature flag will -# be defined for this kernel. -# - -# call script that populates defines automatically -$(if $(shell \ - $(if $(findstring 1,${V}),,QUIET_COMPAT=1) \ - KSRC=${KSRC} OUT=${src}/kcompat_generated_defs.h CONFIG_FILE=${CONFIG_FILE} \ - bash ${src}/kcompat-generator.sh && echo ok), , $(error kcompat-generator.sh failed)) - -################ -# Manual Pages # -################ - -MANSECTION = 7 - -ifeq (,${MANDIR}) - # find the best place to install the man page - MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g') - ifneq (,${MANPATH}) - # test based on inclusion in MANPATH - test_dir = $(findstring ${dir}, ${MANPATH}) - else - # no MANPATH, test based on directory existence - test_dir = $(shell [ -e ${dir} ] && echo ${dir}) - endif - # our preferred install path - # should /usr/local/man be in here ? - MANDIR := /usr/share/man /usr/man - MANDIR := $(foreach dir, ${MANDIR}, ${test_dir}) - MANDIR := $(firstword ${MANDIR}) -endif -ifeq (,${MANDIR}) - # fallback to /usr/man - MANDIR := /usr/man -endif - -#################### -# CCFLAGS variable # -#################### - -# set correct CCFLAGS variable for kernels older than 2.6.24 -ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?)) -CCFLAGS_VAR := EXTRA_CFLAGS -else -CCFLAGS_VAR := ccflags-y -endif - -################# -# KBUILD_OUTPUT # -################# - -# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ -ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ})) -export KBUILD_OUTPUT ?= ${KOBJ} -endif - -############################ -# Module Install Directory # -############################ - -# Default to using updates/drivers/net/ethernet/intel/ path, since depmod since -# v3.1 defaults to checking updates folder first, and only checking kernels/ -# and extra afterwards. We use updates instead of kernel/* due to desire to -# prevent over-writing built-in modules files. -export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/intel/${DRIVER} - -################# -# Auxiliary Bus # -################# - -# If the check_aux_bus script exists, then this driver depends on the -# auxiliary module. Run the script to determine if we need to include -# auxiliary files with this build. -CHECK_AUX_BUS ?= ../scripts/check_aux_bus -ifneq ($(call test_file,${CHECK_AUX_BUS}),) -NEED_AUX_BUS := $(shell ${CHECK_AUX_BUS} --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}" >/dev/null 2>&1; echo $$?) -endif # check_aux_bus exists - -# The out-of-tree auxiliary module we ship should be moved into this -# directory as part of installation. -export INSTALL_AUX_DIR ?= updates/drivers/net/ethernet/intel/auxiliary - -# If we're installing auxiliary bus out-of-tree, the following steps are -# necessary to ensure the relevant files get put in place. -AUX_BUS_HEADERS ?= linux/auxiliary_bus.h auxiliary_compat.h kcompat_generated_defs.h -ifeq (${NEED_AUX_BUS},2) -define auxiliary_post_install - install -D -m 644 Module.symvers ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/intel_auxiliary.symvers - install -d ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR} - mv -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/intel_auxiliary.ko* \ - ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/ - install -d ${INSTALL_MOD_PATH}/${KSRC}/include/linux - install -D -m 644 ${AUX_BUS_HEADERS} -t ${INSTALL_MOD_PATH}/${KSRC}/include/linux -endef -else -auxiliary_post_install = -endif - -ifeq (${NEED_AUX_BUS},2) -define auxiliary_post_uninstall - rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/intel_auxiliary.symvers - rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/intel_auxiliary.ko* - rm -f ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_bus.h - rm -f ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_compat.h - rm -f ${INSTALL_MOD_PATH}/${KSRC}/include/linux/kcompat_generated_defs.h -endef -else -auxiliary_post_uninstall = -endif - -ifeq (${NEED_AUX_BUS},2) -EXTRA_CFLAGS += -DUSE_INTEL_AUX_BUS -endif -###################### -# Kernel Build Macro # -###################### - -# kernel build function -# ${1} is the kernel build target -# ${2} may contain any extra rules to pass directly to the sub-make process -# -# This function is expected to be executed by -# @+$(call kernelbuild,,) -# from within a Makefile recipe. -# -# The following variables are expected to be defined for its use: -# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem -# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS -# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable -# KSRC -- the location of the kernel source tree to build against -# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER -# W -- if set, enables the W= kernel warnings options -# C -- if set, enables the C= kernel sparse build options -# -kernelbuild = ${Q}$(call warn_signed_modules) \ - ${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \ - ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \ - -C "${KSRC}" \ - CONFIG_${DRIVER_UPPERCASE}=m \ - $(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG=n) \ - $(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG_ALL=) \ - M="${CURDIR}" \ - $(if ${W},W="${W}") \ - $(if ${C},C="${C}") \ - $(if ${NEED_AUX_BUS},NEED_AUX_BUS="${NEED_AUX_BUS}") \ - ${2} ${1} diff --git a/idpf.spec b/idpf.spec index 16826d0..448811d 100644 --- a/idpf.spec +++ b/idpf.spec @@ -1,6 +1,6 @@ Name: idpf Summary: Infrastructure Data Path Function Linux Driver -Version: 1.0.2 +Version: 1.0.6 Release: 1 Source: %{name}-%{version}.tar.gz Vendor: Intel Corporation @@ -89,7 +89,7 @@ rm -rf %{buildroot} %doc file.list %doc idpf/pci.updates %doc idpf/COPYING -%doc idpf/README +%doc README %post if [ -d /usr/local/share/%{name} ]; then diff --git a/idpf/src/Makefile b/idpf/src/Makefile index c5c2f0a..40853fd 100644 --- a/idpf/src/Makefile +++ b/idpf/src/Makefile @@ -15,13 +15,13 @@ idpf-y := \ idpf_controlq_setup.o \ idpf_dev.o \ idpf_ethtool.o \ + idpf_idc.o \ idpf_lib.o \ idpf_main.o \ idpf_txrx.o \ idpf_virtchnl.o \ idpf_singleq_txrx.o \ idpf_controlq.o \ - idpf_idc.o \ idpf_xsk.o \ idpf_vf_dev.o idpf-$(CONFIG_PTP_1588_CLOCK:m=y) += idpf_ptp.o idpf_virtchnl_ptp.o diff --git a/idpf/src/common.mk b/idpf/src/common.mk index 90de464..5454c54 100644 --- a/idpf/src/common.mk +++ b/idpf/src/common.mk @@ -347,8 +347,8 @@ ifeq (,${MANDIR}) MANDIR := $(firstword ${MANDIR}) endif ifeq (,${MANDIR}) - # fallback to /usr/man - MANDIR := /usr/man + # fallback to /usr/share/man (FHS standard; legacy /usr/man not present on RHEL 9+) + MANDIR := /usr/share/man endif #################### diff --git a/idpf/src/idpf.h b/idpf/src/idpf.h index e0e2eba..c1b28a3 100644 --- a/idpf/src/idpf.h +++ b/idpf/src/idpf.h @@ -24,6 +24,7 @@ struct idpf_rss_data; #include #include #include +#include #include #include #if IS_ENABLED(CONFIG_ETHTOOL_NETLINK) @@ -55,12 +56,10 @@ struct idpf_rss_data; #endif /* CONFIG_IOMMU_BYPASS */ #define IDPF_DRV_NAME "idpf" -#define IDPF_DRV_VER "1.0.2" +#define IDPF_DRV_VER "1.0.6" #define IDPF_M(m, s) ((m) << (s)) -#include "iidc.h" -#include #include "virtchnl2.h" #include "idpf_txrx.h" #include "idpf_controlq.h" @@ -77,6 +76,21 @@ struct idpf_rss_data; #include "idpf_devlink.h" #endif /* DEVLINK_ENABLED */ #include "idpf_adi.h" +#include "iidc.h" + +#define iidc_rdma_core_auxiliary_drv iidc_auxiliary_drv +#define iidc_rdma_core_dev_info iidc_core_dev_info +#define iidc_rdma_core_auxiliary_dev iidc_auxiliary_dev +#define iidc_rdma_reset_type iidc_reset_type +#define iidc_rdma_event iidc_event + +#define iidc_rdma_event_type iidc_event_type +#define IIDC_RDMA_EVENT_WARN_RESET IIDC_EVENT_WARN_RESET + +#define IIDC_RDMA_EVENT_BEFORE_MTU_CHANGE IIDC_EVENT_BEFORE_MTU_CHANGE +#define IIDC_RDMA_EVENT_AFTER_MTU_CHANGE IIDC_EVENT_AFTER_MTU_CHANGE + +#include "iidc_rdma_idpf.h" #define GETMAXVAL(num_bits) GENMASK((num_bits) - 1, 0) @@ -121,13 +135,6 @@ struct idpf_mac_filter { bool add; }; -struct idpf_rdma_data { - struct iidc_core_dev_info *cdev_info; - struct msix_entry *msix_entries; - int aux_idx; - u16 num_vecs; -}; - /** * enum idpf_state - State machine to handle bring up * @__IDPF_VER_CHECK: Negotiate virtchnl version @@ -273,28 +280,26 @@ struct idpf_vport_max_q { * @ptp_reg_init: PTP register initialization */ struct idpf_reg_ops { - void (*ctlq_reg_init)(struct idpf_hw *hw, + void (*ctlq_reg_init)(struct idpf_adapter *adapter, struct idpf_ctlq_create_info *cq); - int (*intr_reg_init)(struct idpf_vport *vport, struct idpf_intr_grp *intr_grp); void (*mb_intr_reg_init)(struct idpf_adapter *adapter); void (*reset_reg_init)(struct idpf_adapter *adapter); + void (*oicr_reset_reg_init)(struct idpf_adapter *adapter); void (*trigger_reset)(struct idpf_adapter *adapter, enum idpf_flags trig_cause); u64 (*read_master_time)(const struct idpf_hw *hw); void (*ptp_reg_init)(const struct idpf_adapter *adapter); }; -/** - * struct idpf_idc_ops - IDC specific function pointers - * @idc_init: IDC initialization - * @idc_deinit: IDC deinitialization - */ -struct idpf_idc_ops { - int (*idc_init)(struct idpf_adapter *adapter); - void (*idc_deinit)(struct idpf_adapter *adapter); -}; +#define IDPF_MMIO_REG_NUM_STATIC 2 +#define IDPF_PF_MBX_REGION_SZ 4096 +#define IDPF_PF_RSTAT_REGION_SZ 2048 +#define IDPF_VF_MBX_REGION_SZ 10240 +#define IDPF_VF_RSTAT_REGION_SZ 2048 +#define IDPF_SIOV_MBX_REGION_SZ 4096 +#define IDPF_SIOV_RSTAT_REGION_SZ 2048 /** * struct idpf_dev_ops - Device specific operations @@ -304,9 +309,8 @@ struct idpf_idc_ops { #endif * notify_adi_reset: Notify ADI reset * @reg_ops: Register operations - * @idc_ops: IDC operations - * bar0_region1_size: Non-cached BAR0 region 1 size - * bar0_region2_start: Non-cached BAR0 region 2 start address + * idc_init: IDC initialization + * @static_reg_info: array of mailbox and rstat register info */ struct idpf_dev_ops { #if IS_ENABLED(CONFIG_VFIO_MDEV) && defined(HAVE_PASID_SUPPORT) @@ -316,9 +320,10 @@ struct idpf_dev_ops { void (*notify_adi_reset)(struct idpf_adapter *adapter, u16 adi_id, bool reset); struct idpf_reg_ops reg_ops; - struct idpf_idc_ops idc_ops; - resource_size_t bar0_region1_size; - resource_size_t bar0_region2_start; + int (*idc_init)(struct idpf_adapter *adapter); + + /* static_reg_info[0] is mailbox region, static_reg_info[1] is rstat */ + struct resource static_reg_info[IDPF_MMIO_REG_NUM_STATIC]; }; /** @@ -332,7 +337,6 @@ struct idpf_dev_ops { #ifdef HAVE_XDP_SUPPORT * @IDPF_SR_XDP_CHANGE: XDP soft reset #endif - * @IDPF_HR_WARN_RESET: Hard reset warning event to IDC */ enum idpf_vport_reset_cause { IDPF_SR_Q_CHANGE, @@ -344,13 +348,11 @@ enum idpf_vport_reset_cause { #ifdef HAVE_XDP_SUPPORT IDPF_SR_XDP_CHANGE, #endif /* HAVE_XDP_SUPPORT */ - IDPF_HR_WARN_RESET, }; /** * enum idpf_vport_flags - vport flags * @IDPF_VPORT_DEL_QUEUES: To send delete queues message - * @IDPF_VPORT_MTU_CHANGED: vport's MTU has changed, inform AUX driver * @IDPF_VPORT_SW_MARKER: Indicate TX pipe drain software marker packets * processing is done * @IDPF_VPORT_FLAGS_NBITS: Must be last @@ -358,7 +360,6 @@ enum idpf_vport_reset_cause { enum idpf_vport_flags { IDPF_VPORT_DEL_QUEUES, IDPF_VPORT_SW_MARKER, - IDPF_VPORT_MTU_CHANGED, IDPF_VPORT_FLAGS_NBITS, }; @@ -412,6 +413,9 @@ struct idpf_port_stats { u64_stats_t tx_dma_map_errs; u64_stats_t tx_reinjection_timeouts; struct virtchnl2_vport_stats vport_stats; +#ifdef CONFIG_UPLINK_PORT_STATS + struct virtchnl2_phy_port_stats *phy_port_stats; +#endif /* CONFIG_UPLINK_PORT_STATS */ #ifdef IDPF_ADD_PROBES struct idpf_extra_stats extra_stats; #endif /* IDPF_ADD_PROBES */ @@ -497,6 +501,11 @@ struct idpf_vgrp { struct idpf_intr_grp intr_grp; }; +struct idpf_fsteer_fltr { + struct list_head list; + struct ethtool_rx_flow_spec fs; +}; + /** * struct idpf_vport - Handle for netdevices and queue resources * @dflt_grp: Queue and interrupt resource group @@ -523,6 +532,7 @@ struct idpf_vgrp { #ifdef IDPF_ADD_PROBES * @ptype_stats: Ptype statistics #endif + * @vdev_info: IDC vport device info pointer * @adapter: back pointer to associated adapter * @netdev: Associated net_device. Each vport should have one and only one * associated netdev. @@ -544,7 +554,6 @@ struct idpf_vgrp { #ifdef HAVE_ETHTOOL_GET_TS_STATS * @tstamp_stats: TX timestamping statistics #endif - * @finish_reset_task: finish vport's soft reset task */ struct idpf_vport { struct idpf_vgrp dflt_grp; @@ -571,6 +580,9 @@ struct idpf_vport { #ifdef IDPF_ADD_PROBES u64_stats_t ptype_stats[IDPF_RX_MAX_PTYPE]; #endif /* IDPF_ADD_PROBES */ + + struct iidc_rdma_vport_dev_info *vdev_info; + struct idpf_adapter *adapter; struct net_device *netdev; DECLARE_BITMAP(flags, IDPF_VPORT_FLAGS_NBITS); @@ -593,7 +605,6 @@ struct idpf_vport { #ifdef HAVE_ETHTOOL_GET_TS_STATS struct idpf_tstamp_stats tstamp_stats; #endif /* HAVE_ETHTOOL_GET_TS_STATS */ - struct work_struct finish_reset_task; }; /** @@ -660,6 +671,8 @@ struct idpf_q_coalesce { * ethtool * @user_flags: User toggled config flags * @mac_filter_list: List of MAC filters + * @num_fsteer_fltrs: number of flow steering filters + * @flow_steer_list: list of flow steering filters * * Used to restore configuration after a reset as the vport will get wiped. */ @@ -682,6 +695,8 @@ struct idpf_vport_user_config_data { DECLARE_BITMAP(etf_qenable, IDPF_LARGE_MAX_Q); #endif /* HAVE_ETF_SUPPORT */ struct list_head mac_filter_list; + u32 num_fsteer_fltrs; + struct list_head flow_steer_list; }; /** @@ -768,6 +783,7 @@ struct idpf_vec_affinity_config { * @max_q: Maximum possible queues * @req_qs_chunks: Queue chunk data for requested queues * @mac_filter_list_lock: Lock to protect mac filters + * @flow_steer_list_lock: Lock to protect fsteer filters * @flags: See enum idpf_vport_config_flags */ struct idpf_vport_config { @@ -779,6 +795,8 @@ struct idpf_vport_config { #endif /* !HAVE_NETDEV_IRQ_AFFINITY_AND_ARFS */ struct virtchnl2_add_queues *req_qs_chunks; spinlock_t mac_filter_list_lock; + /* protects flow_steer_list */ + spinlock_t flow_steer_list_lock; DECLARE_BITMAP(flags, IDPF_VPORT_CONFIG_FLAGS_NBITS); }; @@ -818,6 +836,12 @@ struct idpf_iommu_bypass { * @num_avail_msix: Available number of MSIX vectors * @num_msix_entries: Number of entries in MSIX table * @msix_entries: MSIX table + * @num_rdma_msix_entries: Available number of MSIX vectors for RDMA + * @rdma_msix_entries: RDMA MSIX table +#ifdef CONFIG_RCA_SUPPORT + * @num_rca_msix_entries: Available number of MSIX vectors for RCA + * @rca_msix_entries: RCA MSIX table +#endif * @req_vec_chunks: Requested vector chunk data * @mb_vector: Mailbox vector data * @vector_stack: Stack to store the msix vector indexes @@ -847,7 +871,7 @@ struct idpf_iommu_bypass { * @vcxn_mngr: Virtchnl transaction manager * @edt_caps: EDT capabilities * @dev_ops: See idpf_dev_ops - * @rdma_data: RDMA data + * @cdev_info: IDC core device info pointer * @num_vfs: Number of allocated VFs through sysfs. PF does not directly talk * to VFs but is used to initialize them * @req_tx_splitq: TX split or single queue model to request @@ -895,6 +919,12 @@ struct idpf_adapter { u16 num_avail_msix; u16 num_msix_entries; struct msix_entry *msix_entries; + u16 num_rdma_msix_entries; + struct msix_entry *rdma_msix_entries; +#ifdef CONFIG_RCA_SUPPORT + u16 num_rca_msix_entries; + struct msix_entry *rca_msix_entries; +#endif /* CONFIG_RCA_SUPPORT */ struct virtchnl2_alloc_vectors *req_vec_chunks; struct idpf_q_vector mb_vector; struct idpf_vector_lifo vector_stack; @@ -926,8 +956,11 @@ struct idpf_adapter { struct idpf_vc_xn_manager *vcxn_mngr; struct virtchnl2_edt_caps edt_caps; +#if defined(CONFIG_OEM_CAPS) || defined(CONFIG_P2P) + struct virtchnl2_oem_caps oem_caps; +#endif /* CONFIG_OEM_CAPS || CONFIG_P2P */ struct idpf_dev_ops dev_ops; - struct idpf_rdma_data rdma_data; + struct iidc_rdma_core_dev_info *cdev_info; int num_vfs; bool req_tx_splitq; bool req_rx_splitq; @@ -1019,21 +1052,14 @@ bool idpf_is_capability_ena(struct idpf_adapter *adapter, bool all, /** * idpf_is_rdma_cap_ena - Determine if RDMA is supported * @adapter: private data struct + * + * Return: true if RDMA capability is enabled, false otherwise */ static inline bool idpf_is_rdma_cap_ena(struct idpf_adapter *adapter) { return idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_RDMA); } -/** - * idpf_get_reserved_rdma_vecs - Get reserved RDMA vectors - * @adapter: private data struct - */ -static inline u16 idpf_get_reserved_rdma_vecs(struct idpf_adapter *adapter) -{ - return le16_to_cpu(adapter->caps.num_rdma_allocated_vectors); -} - #define IDPF_CAP_RSS (\ VIRTCHNL2_FLOW_IPV4_TCP |\ VIRTCHNL2_FLOW_IPV4_TCP |\ @@ -1090,6 +1116,15 @@ static inline u16 idpf_get_reserved_vecs(struct idpf_adapter *adapter) return le16_to_cpu(adapter->caps.num_allocated_vectors); } +/** + * idpf_get_reserved_rdma_vecs - Get reserved RDMA vectors + * @adapter: private data struct + */ +static inline u16 idpf_get_reserved_rdma_vecs(struct idpf_adapter *adapter) +{ + return le16_to_cpu(adapter->caps.num_rdma_allocated_vectors); +} + /** * idpf_get_default_vports - Get default number of vports * @adapter: private data struct @@ -1128,6 +1163,34 @@ static inline u8 idpf_get_min_tx_pkt_len(struct idpf_adapter *adapter) return pkt_len ? pkt_len : IDPF_TX_MIN_PKT_LEN; } +/** + * idpf_get_mbx_reg_addr - Get BAR0 mailbox register address + * @adapter: private data struct + * @reg_offset: register offset value + * + * Return: BAR0 mailbox register address based on register offset. + */ +static inline void __iomem *idpf_get_mbx_reg_addr(struct idpf_adapter *adapter, + resource_size_t reg_offset) +{ + return adapter->hw.mbx.vaddr + reg_offset; +} + +/** + * idpf_get_rstat_reg_addr - Get BAR0 rstat register address + * @adapter: private data struct + * @reg_offset: register offset value + * + * Return: BAR0 rstat register address based on register offset. + */ +static inline void __iomem *idpf_get_rstat_reg_addr(struct idpf_adapter *adapter, + resource_size_t reg_offset) +{ + reg_offset -= adapter->dev_ops.static_reg_info[1].start; + + return adapter->hw.rstat.vaddr + reg_offset; +} + /** * idpf_get_reg_addr - Get BAR0 register address * @adapter: private data struct @@ -1140,11 +1203,28 @@ static inline void __iomem *idpf_get_reg_addr(struct idpf_adapter *adapter, { struct idpf_hw *hw = &adapter->hw; - if (reg_offset < adapter->dev_ops.bar0_region1_size) - return (void __iomem *)(hw->hw_addr + reg_offset); - else - return (void __iomem *)(hw->hw_addr_region2 + reg_offset - - adapter->dev_ops.bar0_region2_start); + for (int i = 0; i < hw->num_lan_regs; i++) { + struct idpf_mmio_reg *region = &hw->lan_regs[i]; + + if (reg_offset >= region->addr_start && + reg_offset < (region->addr_start + region->addr_len)) { + /* Convert the offset so that it is relative to the + * start of the region. Then add the base address of + * the region to get the final address. + */ + reg_offset -= region->addr_start; + + return region->vaddr + reg_offset; + } + } + + /* It's impossible to hit this case with offsets from the CP. But if we + * do for any other reason, the kernel will panic on that register + * access. Might as well do it here to make it clear what's happening. + */ + BUG(); + + return NULL; } /** @@ -1215,6 +1295,32 @@ static inline u16 idpf_get_max_tx_hdr_size(struct idpf_adapter *adapter) } #endif /* HAVE_NDO_FEATURES_CHECK */ +#if defined(CONFIG_OEM_CAPS) || defined(CONFIG_P2P) +/** + * idpf_is_oem_cap_ena - Implementation of oem caps checking + * @adapter: private data struct + * @oem_cap: capability to check + */ +static inline bool idpf_is_oem_cap_ena(struct idpf_adapter *adapter, + u64 oem_cap) +{ + u64 oem_caps = le64_to_cpu(adapter->oem_caps.oem_caps); + + return !!(oem_caps & oem_cap); +} + +#endif /* CONFIG_OEM_CAPS || CONFIG_P2P */ +#ifdef CONFIG_RCA_SUPPORT +/** + * idpf_is_rca_enabled - check if RCA is enabled + * @adapter: private data struct + */ +static inline bool idpf_is_rca_enabled(struct idpf_adapter *adapter) +{ + return idpf_is_oem_cap_ena(adapter, VIRTCHNL2_CAP_OEM_RCA); +} + +#endif /* CONFIG_RCA_SUPPORT */ /** * idpf_vport_init_lock -Acquire the init/deinit control lock. It * controls and protect initialization, re-initialization and @@ -1262,12 +1368,12 @@ void idpf_statistics_task(struct work_struct *work); void idpf_init_task(struct work_struct *work); void idpf_service_task(struct work_struct *work); void idpf_mbx_task(struct work_struct *work); -void idpf_finish_soft_reset(struct work_struct *work); void idpf_vc_event_task(struct work_struct *work); void idpf_dev_ops_init(struct idpf_adapter *adapter); void idpf_vf_dev_ops_init(struct idpf_adapter *adapter); void idpf_vport_adjust_qs(struct idpf_vport *vport); int idpf_intr_req(struct idpf_adapter *adapter); +void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter); void idpf_intr_rel(struct idpf_adapter *adapter); #ifdef HAVE_NDO_FEATURES_CHECK u16 idpf_get_max_tx_hdr_size(struct idpf_adapter *adapter); @@ -1290,6 +1396,14 @@ bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val); #else void idpf_vport_set_hsplit(struct idpf_vport *vport, bool ena); #endif /* CONFIG_ETHTOOL_NETLINK && HAVE_ETHTOOL_SUPPORT_TCP_DATA_SPLIT */ +int idpf_idc_init(struct idpf_adapter *adapter); +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter, + enum iidc_function_type ftype); +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info); +void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info); +void idpf_idc_issue_reset_event(struct iidc_rdma_core_dev_info *cdev_info); +void idpf_idc_vdev_mtu_event(struct iidc_rdma_vport_dev_info *vdev_info, + enum iidc_rdma_event_type event_type); #ifdef DEVLINK_ENABLED void idpf_vport_dealloc(struct idpf_vport *vport); #endif /* DEVLINK_ENABLED */ @@ -1306,8 +1420,8 @@ int idpf_set_promiscuous(struct idpf_adapter *adapter, struct virtchnl2_queue_reg_chunks * idpf_get_queue_reg_chunks(struct idpf_vport *vport); int idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q); -void idpf_netdev_stop_all(struct idpf_adapter *adapter); -void idpf_device_detach(struct idpf_adapter *adapter); +void idpf_detach_and_close(struct idpf_adapter *adapter); +void idpf_attach_and_open(struct idpf_adapter *adapter); int idpf_check_reset_complete(struct idpf_adapter *adapter); int idpf_reset_recover(struct idpf_adapter *adapter); bool idpf_is_reset_detected(struct idpf_adapter *adapter); @@ -1315,7 +1429,6 @@ int idpf_vport_queue_ids_init(struct idpf_q_grp *q_grp, struct virtchnl2_queue_reg_chunks *chunks); int idpf_queue_reg_init(struct idpf_vport *vport, struct idpf_q_grp *q_grp, struct virtchnl2_queue_reg_chunks *chunks); -void idpf_set_vport_state(struct idpf_adapter *adapter); int idpf_check_supported_desc_ids(struct idpf_vport *vport); void idpf_vport_intr_write_itr(struct idpf_q_vector *q_vector, u16 itr, bool tx); @@ -1332,16 +1445,6 @@ void idpf_xdp_flush(struct net_device *dev); #endif /* HAVE_XDP_SUPPORT */ int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs); int idpf_sriov_config_vfs(struct pci_dev *pdev, int num_vfs); -int idpf_idc_init(struct idpf_adapter *adapter); -void idpf_idc_deinit(struct idpf_adapter *adapter); -int -idpf_idc_init_aux_device(struct idpf_rdma_data *rdma_data, - enum iidc_function_type ftype); -void idpf_idc_deinit_aux_device(struct idpf_adapter *adapter); -int idpf_idc_vc_receive(struct idpf_rdma_data *rdma_data, u32 f_id, const u8 *msg, - u16 msg_size); -void idpf_idc_event(struct idpf_rdma_data *rdma_data, - enum iidc_event_type event_type); /** * idpf_is_feature_ena - Determine if a particular feature is enabled * @vport: Vport to check diff --git a/idpf/src/idpf_adi.c b/idpf/src/idpf_adi.c index 6fbce4b..d38561a 100644 --- a/idpf/src/idpf_adi.c +++ b/idpf/src/idpf_adi.c @@ -442,12 +442,13 @@ static int idpf_adi_config(struct idpf_adi *adi, u32 pasid, bool ena) static u32 idpf_adi_read_reg32(struct idpf_adi *adi, size_t offs) { struct idpf_adi_priv *priv = idpf_get_adi_priv(adi); - struct idpf_adapter *adapter; + struct idpf_adapter *adapter = priv->adapter; - adapter = priv->adapter; - switch (offs) { - case VFGEN_RSTAT: + /* Account for static rstat region start */ + if (offs == VFGEN_RSTAT) return priv->reset_state; + + switch (offs) { case VF_ATQBAL: return readl(idpf_get_reg_addr(adapter, PF_MBX_ATQBAL(priv->mbx_id))); case VF_ATQBAH: diff --git a/idpf/src/idpf_controlq.c b/idpf/src/idpf_controlq.c index 26c7d71..e33e9a5 100644 --- a/idpf/src/idpf_controlq.c +++ b/idpf/src/idpf_controlq.c @@ -95,7 +95,7 @@ static void idpf_ctlq_init_rxq_bufs(struct idpf_ctlq_info *cq) */ static void idpf_ctlq_shutdown(struct idpf_hw *hw, struct idpf_ctlq_info *cq) { - spin_lock(&cq->cq_lock); + WARN_ON(spin_is_locked(&cq->cq_lock)); if (IS_SIMICS_DEVICE(hw->subsystem_device_id)) { wr32(hw, cq->reg.head, 0); @@ -110,8 +110,6 @@ static void idpf_ctlq_shutdown(struct idpf_hw *hw, struct idpf_ctlq_info *cq) /* Set ring_size to 0 to indicate uninitialized queue */ cq->ring_size = 0; - - spin_unlock(&cq->cq_lock); } /** @@ -411,7 +409,7 @@ static int __idpf_ctlq_clean_sq(struct idpf_ctlq_info *cq, u16 *clean_count, break; /* This barrier is needed to ensure that no other fields - * are read until we check the DD flag + * are read until we check the DD flag */ dma_rmb(); /* strip off FW internal code */ @@ -657,7 +655,7 @@ int idpf_ctlq_recv(struct idpf_ctlq_info *cq, u16 *num_q_msg, break; /* This barrier is needed to ensure that no other fields - * are read until we check the DD flag + * are read until we check the DD flag */ dma_rmb(); ret_val = le16_to_cpu(desc->ret_val); diff --git a/idpf/src/idpf_controlq_api.h b/idpf/src/idpf_controlq_api.h index 0ae06c3..9c07b2c 100644 --- a/idpf/src/idpf_controlq_api.h +++ b/idpf/src/idpf_controlq_api.h @@ -149,18 +149,30 @@ enum idpf_mbx_opc { idpf_mbq_opc_send_msg_to_peer_drv = 0x0804, }; +/* Max number of MMIO regions not including the mailbox and rstat regions in + * the fallback case when the whole bar is mapped. + */ +#define IDPF_MMIO_MAP_FALLBACK_MAX_REMAINING 3 + +struct idpf_mmio_reg { + void __iomem *vaddr; + resource_size_t addr_start; + resource_size_t addr_len; +}; + /* Define the APF hardware struct to replace other control structs as needed * Align to ctlq_hw_info */ struct idpf_hw { - /* Some part of BAR0 address space is not mapped by the LAN driver. - * This results in 2 regions of BAR0 to be mapped by LAN driver which - * will have its own base hardware address when mapped. + /* Some parts of BAR0 address space are not mapped by the LAN driver. + * This results in multiple regions of BAR0 mapped by LAN driver which + * will have their own base hardware address when mapped. */ - void __iomem *hw_addr; - void __iomem *hw_addr_region2; - resource_size_t hw_addr_len; - resource_size_t hw_addr_region2_len; + struct idpf_mmio_reg mbx; + struct idpf_mmio_reg rstat; + /* Array of remaining LAN BAR regions */ + int num_lan_regs; + struct idpf_mmio_reg *lan_regs; void *back; /* control queue - send and receive */ @@ -196,7 +208,7 @@ int idpf_ctlq_add(struct idpf_hw *hw, void idpf_ctlq_remove(struct idpf_hw *hw, struct idpf_ctlq_info *cq); -/* Sends messages to HW and will also free the buffer*/ +/* Sends messages to HW and will also free the buffer */ int idpf_ctlq_send(struct idpf_hw *hw, struct idpf_ctlq_info *cq, u16 num_q_msg, diff --git a/idpf/src/idpf_dev.c b/idpf/src/idpf_dev.c index 473753a..872880c 100644 --- a/idpf/src/idpf_dev.c +++ b/idpf/src/idpf_dev.c @@ -8,13 +8,6 @@ /* LAN driver does not own all the BAR0 address space. This results in 2 BAR0 * regions for PF device and the driver should map each region separately. - * - * Rest of BAR0 is owned by RDMA and it maps the pages on its own as it needs - * to map some of the pages for write combing (WC) instead of the default - * non-cached (NC) mapping that LAN driver does. In the PF BAR space, - * RDMA BAR0 memory lies between 192MB to 256MB. - * - * Also driver should map 1 page of RDMA from its space. */ #define IDPF_PF_BAR0_REGION1_END 0xC001000 /* 192MB + 4KB */ #define IDPF_PF_BAR0_REGION2_START 0x10000000 /* 256MB */ @@ -23,12 +16,13 @@ /** * idpf_ctlq_reg_init - initialize default mailbox registers - * @hw: pointer to the hardware structure + * @adapter: adapter structure * @cq: pointer to the array of create control queues */ -static void idpf_ctlq_reg_init(struct idpf_hw *hw, +static void idpf_ctlq_reg_init(struct idpf_adapter *adapter, struct idpf_ctlq_create_info *cq) { + resource_size_t mbx_start = adapter->dev_ops.static_reg_info[0].start; int i; for (i = 0; i < IDPF_NUM_DFLT_MBX_Q; i++) { @@ -37,22 +31,22 @@ static void idpf_ctlq_reg_init(struct idpf_hw *hw, switch (ccq->type) { case IDPF_CTLQ_TYPE_MAILBOX_TX: /* set head and tail registers in our local struct */ - ccq->reg.head = PF_FW_ATQH; - ccq->reg.tail = PF_FW_ATQT; - ccq->reg.len = PF_FW_ATQLEN; - ccq->reg.bah = PF_FW_ATQBAH; - ccq->reg.bal = PF_FW_ATQBAL; + ccq->reg.head = PF_FW_ATQH - mbx_start; + ccq->reg.tail = PF_FW_ATQT - mbx_start; + ccq->reg.len = PF_FW_ATQLEN - mbx_start; + ccq->reg.bah = PF_FW_ATQBAH - mbx_start; + ccq->reg.bal = PF_FW_ATQBAL - mbx_start; ccq->reg.len_mask = PF_FW_ATQLEN_ATQLEN_M; ccq->reg.len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M; ccq->reg.head_mask = PF_FW_ATQH_ATQH_M; break; case IDPF_CTLQ_TYPE_MAILBOX_RX: /* set head and tail registers in our local struct */ - ccq->reg.head = PF_FW_ARQH; - ccq->reg.tail = PF_FW_ARQT; - ccq->reg.len = PF_FW_ARQLEN; - ccq->reg.bah = PF_FW_ARQBAH; - ccq->reg.bal = PF_FW_ARQBAL; + ccq->reg.head = PF_FW_ARQH - mbx_start; + ccq->reg.tail = PF_FW_ARQT - mbx_start; + ccq->reg.len = PF_FW_ARQLEN - mbx_start; + ccq->reg.bah = PF_FW_ARQBAH - mbx_start; + ccq->reg.bal = PF_FW_ARQBAL - mbx_start; ccq->reg.len_mask = PF_FW_ARQLEN_ARQLEN_M; ccq->reg.len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M; ccq->reg.head_mask = PF_FW_ARQH_ARQH_M; @@ -147,8 +141,16 @@ static int idpf_intr_reg_init(struct idpf_vport *vport, */ static void idpf_reset_reg_init(struct idpf_adapter *adapter) { - adapter->reset_reg.rstat = idpf_get_reg_addr(adapter, PFGEN_RSTAT); + adapter->reset_reg.rstat = idpf_get_rstat_reg_addr(adapter, PFGEN_RSTAT); adapter->reset_reg.rstat_m = PFGEN_RSTAT_PFR_STATE_M; +} + +/** + * idpf_oicr_reset_reg_init - Initialize reset registers + * @adapter: Driver specific private structure + */ +static void idpf_oicr_reset_reg_init(struct idpf_adapter *adapter) +{ adapter->reset_reg.oicr_cause = idpf_get_reg_addr(adapter, PF_INT_DIR_OICR_CAUSE); adapter->reset_reg.oicr_cause_m = PF_INT_DIR_OICR_CAUSE_CAUSE_M; } @@ -163,9 +165,9 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter, { u32 reset_reg; - reset_reg = readl(idpf_get_reg_addr(adapter, PFGEN_CTRL)); + reset_reg = readl(idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL)); writel(reset_reg | PFGEN_CTRL_PFSWR, - idpf_get_reg_addr(adapter, PFGEN_CTRL)); + idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL)); } /** @@ -206,22 +208,14 @@ static void idpf_ptp_reg_init(const struct idpf_adapter *adapter) } /** - * idpf_idc_register - idc register function for idpf + * idpf_idc_register - register for IDC callbacks * @adapter: Driver specific private structure + * + * Return: 0 on success or error code on failure. */ static int idpf_idc_register(struct idpf_adapter *adapter) { - return idpf_idc_init_aux_device(&adapter->rdma_data, IIDC_FUNCTION_TYPE_PF); -} - -/** - * idpf_idc_ops_init - Initialize IDC function pointers - * @adapter: Driver specific private structure - */ -static void idpf_idc_ops_init(struct idpf_adapter *adapter) -{ - adapter->dev_ops.idc_ops.idc_init = idpf_idc_register; - adapter->dev_ops.idc_ops.idc_deinit = idpf_idc_deinit_aux_device; + return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_PF); } /** @@ -234,6 +228,7 @@ static void idpf_reg_ops_init(struct idpf_adapter *adapter) adapter->dev_ops.reg_ops.intr_reg_init = idpf_intr_reg_init; adapter->dev_ops.reg_ops.mb_intr_reg_init = idpf_mb_intr_reg_init; adapter->dev_ops.reg_ops.reset_reg_init = idpf_reset_reg_init; + adapter->dev_ops.reg_ops.oicr_reset_reg_init = idpf_oicr_reset_reg_init; adapter->dev_ops.reg_ops.trigger_reset = idpf_trigger_reset; adapter->dev_ops.reg_ops.read_master_time = idpf_read_master_time_ns; adapter->dev_ops.reg_ops.ptp_reg_init = idpf_ptp_reg_init; @@ -246,13 +241,16 @@ static void idpf_reg_ops_init(struct idpf_adapter *adapter) void idpf_dev_ops_init(struct idpf_adapter *adapter) { idpf_reg_ops_init(adapter); - idpf_idc_ops_init(adapter); #if IS_ENABLED(CONFIG_VFIO_MDEV) && defined(HAVE_PASID_SUPPORT) adapter->dev_ops.vdcm_init = idpf_vdcm_init; adapter->dev_ops.vdcm_deinit = idpf_vdcm_deinit; adapter->dev_ops.notify_adi_reset = idpf_notify_adi_reset; #endif /* CONFIG_VFIO_MDEV && HAVE_PASID_SUPPORT */ - adapter->dev_ops.bar0_region1_size = IDPF_PF_BAR0_REGION1_END; - adapter->dev_ops.bar0_region2_start = IDPF_PF_BAR0_REGION2_START; + adapter->dev_ops.idc_init = idpf_idc_register; + + resource_set_range(&adapter->dev_ops.static_reg_info[0], + PF_FW_BASE, IDPF_PF_MBX_REGION_SZ); + resource_set_range(&adapter->dev_ops.static_reg_info[1], + PFGEN_RTRIG, IDPF_PF_RSTAT_REGION_SZ); } diff --git a/idpf/src/idpf_ethtool.c b/idpf/src/idpf_ethtool.c index 7c31485..efeb7d0 100644 --- a/idpf/src/idpf_ethtool.c +++ b/idpf/src/idpf_ethtool.c @@ -5,6 +5,7 @@ #include #include "idpf.h" #include "idpf_ptp.h" +#include "idpf_virtchnl.h" #ifdef SIOCETHTOOL #ifdef ETHTOOL_GRXRINGS @@ -18,31 +19,327 @@ */ #ifdef HAVE_ETHTOOL_GET_RXNFC_VOID_RULE_LOCS static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, - void __always_unused *rule_locs) + void *rule_locs) #else static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, - u32 __always_unused *rule_locs) + u32 *rule_locs) #endif { struct idpf_adapter *adapter = idpf_netdev_to_adapter(netdev); + struct idpf_netdev_priv *np = netdev_priv(netdev); + struct idpf_vport_user_config_data *user_config; + struct idpf_vport_config *vport_config; + struct idpf_fsteer_fltr *f; struct idpf_vport *vport; + unsigned int cnt = 0; + int err = 0; idpf_vport_cfg_lock(adapter); vport = idpf_netdev_to_vport(netdev); + vport_config = np->adapter->vport_config[np->vport_idx]; + user_config = &vport_config->user_config; switch (cmd->cmd) { case ETHTOOL_GRXRINGS: cmd->data = vport->dflt_grp.q_grp.num_rxq; - idpf_vport_cfg_unlock(adapter); - - return 0; + break; + case ETHTOOL_GRXCLSRLCNT: + cmd->rule_cnt = user_config->num_fsteer_fltrs; + cmd->data = idpf_fsteer_max_rules(vport); + break; + case ETHTOOL_GRXCLSRULE: + err = -ENOENT; + spin_lock_bh(&vport_config->flow_steer_list_lock); + list_for_each_entry(f, &user_config->flow_steer_list, list) + if (f->fs.location == cmd->fs.location) { + /* Avoid infoleak from padding: zero first, + * then assign fields + */ + memset(&cmd->fs, 0, sizeof(cmd->fs)); + cmd->fs = f->fs; + err = 0; + break; + } + spin_unlock_bh(&vport_config->flow_steer_list_lock); + break; + case ETHTOOL_GRXCLSRLALL: + cmd->data = idpf_fsteer_max_rules(vport); + spin_lock_bh(&vport_config->flow_steer_list_lock); + list_for_each_entry(f, &user_config->flow_steer_list, list) { + if (cnt == cmd->rule_cnt) { + err = -EMSGSIZE; + break; + } + rule_locs[cnt] = f->fs.location; + cnt++; + } + if (!err) + cmd->rule_cnt = user_config->num_fsteer_fltrs; + spin_unlock_bh(&vport_config->flow_steer_list_lock); + break; default: break; } idpf_vport_cfg_unlock(adapter); - return -EOPNOTSUPP; + return err; +} + +static void idpf_fsteer_fill_ipv4(struct virtchnl2_proto_hdrs *hdrs, + struct ethtool_rx_flow_spec *fsp) +{ + struct iphdr *iph; + + hdrs->proto_hdr[0].hdr_type = cpu_to_le32(VIRTCHNL2_PROTO_HDR_IPV4); + + iph = (struct iphdr *)hdrs->proto_hdr[0].buffer_spec; + iph->saddr = fsp->h_u.tcp_ip4_spec.ip4src; + iph->daddr = fsp->h_u.tcp_ip4_spec.ip4dst; + + iph = (struct iphdr *)hdrs->proto_hdr[0].buffer_mask; + iph->saddr = fsp->m_u.tcp_ip4_spec.ip4src; + iph->daddr = fsp->m_u.tcp_ip4_spec.ip4dst; +} + +static void idpf_fsteer_fill_udp(struct virtchnl2_proto_hdrs *hdrs, + struct ethtool_rx_flow_spec *fsp, + bool v4) +{ + struct udphdr *udph, *udpm; + + hdrs->proto_hdr[1].hdr_type = cpu_to_le32(VIRTCHNL2_PROTO_HDR_UDP); + + udph = (struct udphdr *)hdrs->proto_hdr[1].buffer_spec; + udpm = (struct udphdr *)hdrs->proto_hdr[1].buffer_mask; + + if (v4) { + udph->source = fsp->h_u.udp_ip4_spec.psrc; + udph->dest = fsp->h_u.udp_ip4_spec.pdst; + udpm->source = fsp->m_u.udp_ip4_spec.psrc; + udpm->dest = fsp->m_u.udp_ip4_spec.pdst; + } else { + udph->source = fsp->h_u.udp_ip6_spec.psrc; + udph->dest = fsp->h_u.udp_ip6_spec.pdst; + udpm->source = fsp->m_u.udp_ip6_spec.psrc; + udpm->dest = fsp->m_u.udp_ip6_spec.pdst; + } +} + +static void idpf_fsteer_fill_tcp(struct virtchnl2_proto_hdrs *hdrs, + struct ethtool_rx_flow_spec *fsp, + bool v4) +{ + struct tcphdr *tcph, *tcpm; + + hdrs->proto_hdr[1].hdr_type = cpu_to_le32(VIRTCHNL2_PROTO_HDR_TCP); + + tcph = (struct tcphdr *)hdrs->proto_hdr[1].buffer_spec; + tcpm = (struct tcphdr *)hdrs->proto_hdr[1].buffer_mask; + + if (v4) { + tcph->source = fsp->h_u.tcp_ip4_spec.psrc; + tcph->dest = fsp->h_u.tcp_ip4_spec.pdst; + tcpm->source = fsp->m_u.tcp_ip4_spec.psrc; + tcpm->dest = fsp->m_u.tcp_ip4_spec.pdst; + } else { + tcph->source = fsp->h_u.tcp_ip6_spec.psrc; + tcph->dest = fsp->h_u.tcp_ip6_spec.pdst; + tcpm->source = fsp->m_u.tcp_ip6_spec.psrc; + tcpm->dest = fsp->m_u.tcp_ip6_spec.pdst; + } +} + +/** + * idpf_add_flow_steer - add a Flow Steering filter + * @netdev: network interface device structure + * @cmd: command to add Flow Steering filter + * + * Return: 0 on success and negative values for failure + */ +static int idpf_add_flow_steer(struct net_device *netdev, + struct ethtool_rxnfc *cmd) +{ + struct idpf_fsteer_fltr *fltr, *parent = NULL, *f; + struct idpf_netdev_priv *np = netdev_priv(netdev); + struct idpf_vport_user_config_data *user_config; + struct ethtool_rx_flow_spec *fsp = &cmd->fs; + struct virtchnl2_flow_rule_add_del *rule; + struct idpf_vport_config *vport_config; + struct virtchnl2_rule_action_set *acts; + struct virtchnl2_flow_rule_info *info; + struct virtchnl2_proto_hdrs *hdrs; + struct idpf_vport *vport; + u32 flow_type, q_index; + u16 num_rxq; + int err = 0; + + vport = idpf_netdev_to_vport(netdev); + vport_config = vport->adapter->vport_config[np->vport_idx]; + user_config = &vport_config->user_config; + num_rxq = user_config->num_req_rx_qs; + + flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); + if (flow_type != fsp->flow_type) + return -EINVAL; + + if (!idpf_sideband_action_ena(vport, fsp) || + !idpf_sideband_flow_type_ena(vport, flow_type)) + return -EOPNOTSUPP; + + if (user_config->num_fsteer_fltrs > idpf_fsteer_max_rules(vport)) + return -ENOSPC; + + q_index = fsp->ring_cookie; + if (q_index >= num_rxq) + return -EINVAL; + + rule = kzalloc(struct_size(rule, rule_info, 1), GFP_KERNEL); + if (!rule) + return -ENOMEM; + + fltr = kzalloc(sizeof(*fltr), GFP_KERNEL); + if (!fltr) { + err = -ENOMEM; + goto out_free_rule; + } + + /* detect duplicate entry and reject before adding rules */ + spin_lock_bh(&vport_config->flow_steer_list_lock); + list_for_each_entry(f, &user_config->flow_steer_list, list) { + if (f->fs.location == fsp->location) { + err = -EEXIST; + break; + } + + if (f->fs.location > fsp->location) + break; + parent = f; + } + spin_unlock_bh(&vport_config->flow_steer_list_lock); + + if (err) + goto out; + + rule->vport_id = cpu_to_le32(vport->vport_id); + rule->count = cpu_to_le32(1); + info = &rule->rule_info[0]; + info->rule_id = cpu_to_le32(fsp->location); + + hdrs = &info->rule_cfg.proto_hdrs; + hdrs->tunnel_level = 0; + hdrs->count = cpu_to_le32(2); + + acts = &info->rule_cfg.action_set; + acts->count = cpu_to_le32(1); + acts->actions[0].action_type = cpu_to_le32(VIRTCHNL2_ACTION_QUEUE); + acts->actions[0].act_conf.q_id = cpu_to_le32(q_index); + + switch (flow_type) { + case UDP_V4_FLOW: + idpf_fsteer_fill_ipv4(hdrs, fsp); + idpf_fsteer_fill_udp(hdrs, fsp, true); + break; + case TCP_V4_FLOW: + idpf_fsteer_fill_ipv4(hdrs, fsp); + idpf_fsteer_fill_tcp(hdrs, fsp, true); + break; + default: + err = -EINVAL; + goto out; + } + + err = idpf_add_del_fsteer_filters(vport->adapter, rule, + VIRTCHNL2_OP_ADD_FLOW_RULE); + if (err) + goto out; + + if (info->status != cpu_to_le32(VIRTCHNL2_FLOW_RULE_SUCCESS)) { + err = -EIO; + goto out; + } + + /* Save a copy of the user's flow spec so ethtool can later retrieve it */ + fltr->fs = *fsp; + + spin_lock_bh(&vport_config->flow_steer_list_lock); + parent ? list_add(&fltr->list, &parent->list) : + list_add(&fltr->list, &user_config->flow_steer_list); + + user_config->num_fsteer_fltrs++; + spin_unlock_bh(&vport_config->flow_steer_list_lock); + goto out_free_rule; + +out: + kfree(fltr); +out_free_rule: + kfree(rule); + return err; +} + +/** + * idpf_del_flow_steer - delete a Flow Steering filter + * @netdev: network interface device structure + * @cmd: command to delete Flow Steering filter + * + * Return: 0 on success and negative values for failure + */ +static int idpf_del_flow_steer(struct net_device *netdev, + struct ethtool_rxnfc *cmd) +{ + struct idpf_netdev_priv *np = netdev_priv(netdev); + struct idpf_vport_user_config_data *user_config; + struct ethtool_rx_flow_spec *fsp = &cmd->fs; + struct virtchnl2_flow_rule_add_del *rule; + struct idpf_vport_config *vport_config; + struct virtchnl2_flow_rule_info *info; + struct idpf_fsteer_fltr *f, *iter; + struct idpf_vport *vport; + int err; + + vport = idpf_netdev_to_vport(netdev); + vport_config = vport->adapter->vport_config[np->vport_idx]; + user_config = &vport_config->user_config; + + if (!idpf_sideband_action_ena(vport, fsp)) + return -EOPNOTSUPP; + + rule = kzalloc(struct_size(rule, rule_info, 1), GFP_KERNEL); + if (!rule) + return -ENOMEM; + + rule->vport_id = cpu_to_le32(vport->vport_id); + rule->count = cpu_to_le32(1); + info = &rule->rule_info[0]; + info->rule_id = cpu_to_le32(fsp->location); + + err = idpf_add_del_fsteer_filters(vport->adapter, rule, + VIRTCHNL2_OP_DEL_FLOW_RULE); + if (err) + goto out; + + if (info->status != cpu_to_le32(VIRTCHNL2_FLOW_RULE_SUCCESS)) { + err = -EIO; + goto out; + } + + spin_lock_bh(&vport_config->flow_steer_list_lock); + list_for_each_entry_safe(f, iter, + &user_config->flow_steer_list, list) { + if (f->fs.location == fsp->location) { + list_del(&f->list); + kfree(f); + user_config->num_fsteer_fltrs--; + goto out_unlock; + } + } + err = -ENOENT; + +out_unlock: + spin_unlock_bh(&vport_config->flow_steer_list_lock); +out: + kfree(rule); + return err; } /** @@ -54,10 +351,26 @@ static int idpf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, */ static int idpf_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) { - return -EOPNOTSUPP; -} + struct idpf_adapter *adapter = idpf_netdev_to_adapter(netdev); + int ret = -EOPNOTSUPP; + idpf_vport_cfg_lock(adapter); + switch (cmd->cmd) { + case ETHTOOL_SRXCLSRLINS: + ret = idpf_add_flow_steer(netdev, cmd); + break; + case ETHTOOL_SRXCLSRLDEL: + ret = idpf_del_flow_steer(netdev, cmd); + break; + default: + break; + } + + idpf_vport_cfg_unlock(adapter); + return ret; +} #endif /* ETHTOOL_GRXRINGS */ + #if defined(ETHTOOL_GRSSH) && defined(ETHTOOL_SRSSH) /** * idpf_get_rxfh_key_size - get the RSS hash key size @@ -614,6 +927,59 @@ static const struct idpf_stats idpf_gstrings_port_stats[] = { #define IDPF_PTYPE_STATS_LEN IDPF_RX_MAX_PTYPE #endif /* IDPF_ADD_PROBES */ +#ifdef CONFIG_UPLINK_PORT_STATS +#define IDPF_PHY_PORT_STAT(_name, _stat) \ + IDPF_STAT(struct virtchnl2_phy_port_stats, _name, _stat) + +static const struct idpf_stats idpf_gstrings_phy_port_stats[] = { + IDPF_PHY_PORT_STAT("port-rx_bytes", rx_bytes), + IDPF_PHY_PORT_STAT("port-rx-unicast_pkts", rx_unicast_pkts), + IDPF_PHY_PORT_STAT("port-rx-multicast_pkts", rx_multicast_pkts), + IDPF_PHY_PORT_STAT("port-rx-broadcast_pkts", rx_broadcast_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-64_pkts", rx_size_64_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-127_pkts", rx_size_127_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-255_pkts", rx_size_255_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-511_pkts", rx_size_511_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-1023_pkts", rx_size_1023_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-1518_pkts", rx_size_1518_pkts), + IDPF_PHY_PORT_STAT("port-rx_size-jumbo_pkts", rx_size_jumbo_pkts), + IDPF_PHY_PORT_STAT("port-rx-xon_events", rx_xon_events), + IDPF_PHY_PORT_STAT("port-rx-xoff_events", rx_xoff_events), + IDPF_PHY_PORT_STAT("port-rx-undersized_pkts", rx_undersized_pkts), + IDPF_PHY_PORT_STAT("port-rx-fragmented_pkts", rx_fragmented_pkts), + IDPF_PHY_PORT_STAT("port-rx-oversized_pkts", rx_oversized_pkts), + IDPF_PHY_PORT_STAT("port-rx-jabber_pkts", rx_jabber_pkts), + IDPF_PHY_PORT_STAT("port-rx-csum_errors", rx_csum_errors), + IDPF_PHY_PORT_STAT("port-rx-length_errors", rx_length_errors), + IDPF_PHY_PORT_STAT("port-rx-dropped_pkts", rx_dropped_pkts), + IDPF_PHY_PORT_STAT("port-rx-crc_errors", rx_crc_errors), + IDPF_PHY_PORT_STAT("port-rx-runt_errors", rx_runt_errors), + IDPF_PHY_PORT_STAT("port-rx-illegal_bytes", rx_illegal_bytes), + IDPF_PHY_PORT_STAT("port-rx-total_pkts", rx_total_pkts), + IDPF_PHY_PORT_STAT("port-tx-bytes", tx_bytes), + IDPF_PHY_PORT_STAT("port-tx-unicast_pkts", tx_unicast_pkts), + IDPF_PHY_PORT_STAT("port-tx-multicast_pkts", tx_multicast_pkts), + IDPF_PHY_PORT_STAT("port-tx-broadcast_pkts", tx_broadcast_pkts), + IDPF_PHY_PORT_STAT("port-tx-errors", tx_errors), + IDPF_PHY_PORT_STAT("port-tx-timeout_events", tx_timeout_events), + IDPF_PHY_PORT_STAT("port-tx_size-64_pkts", tx_size_64_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-127_pkts", tx_size_127_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-255_pkts", tx_size_255_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-511_pkts", tx_size_511_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-1023_pkts", tx_size_1023_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-1518_pkts", tx_size_1518_pkts), + IDPF_PHY_PORT_STAT("port-tx_size-jumbo_pkts", tx_size_jumbo_pkts), + IDPF_PHY_PORT_STAT("port-tx-xon_events", tx_xon_events), + IDPF_PHY_PORT_STAT("port-tx-xoff_events", tx_xoff_events), + IDPF_PHY_PORT_STAT("port-tx-dropped_link_down_pkts", tx_dropped_link_down_pkts), + IDPF_PHY_PORT_STAT("port-tx-total_pkts", tx_total_pkts), + IDPF_PHY_PORT_STAT("port-mac-local_faults", mac_local_faults), + IDPF_PHY_PORT_STAT("port-mac-remote_faults", mac_remote_faults), +}; + +#define IDPF_PHY_PORT_STATS_LEN ARRAY_SIZE(idpf_gstrings_phy_port_stats) + +#endif /* CONFIG_UPLINK_PORT_STATS */ struct idpf_priv_flags { char flag_string[ETH_GSTRING_LEN]; bool read_only; @@ -688,6 +1054,15 @@ static void idpf_add_stat_strings(u8 **p, const struct idpf_stats *stats, #else ethtool_sprintf(p, "%s", stats[i].stat_string); #endif /* HAVE_ETHTOOL_PUTS */ +#ifdef CONFIG_UPLINK_PORT_STATS + /* Return early for uplink port stats since this function will be + * called again immediately to include the standard stats strings. + * Otherwise, we will add the lso/gro_hw strings twice. + */ + if (stats == idpf_gstrings_phy_port_stats) + return; + +#endif /* CONFIG_UPLINK_PORT_STATS */ for (i = 0; i < IDPF_MAX_SEGS; i++) ethtool_sprintf(p, "lso_num_segs_%u", i + 1); for (i = 0; i < IDPF_MAX_SEGS; i++) @@ -712,6 +1087,11 @@ static void idpf_get_stat_strings(struct net_device *netdev, u8 *data) unsigned int i; vport_config = np->adapter->vport_config[np->vport_idx]; +#ifdef CONFIG_UPLINK_PORT_STATS + if (test_bit(IDPF_VPORT_UPLINK_PORT, vport_config->flags)) + idpf_add_stat_strings(&data, idpf_gstrings_phy_port_stats, + IDPF_PHY_PORT_STATS_LEN); +#endif /* CONFIG_UPLINK_PORT_STATS */ idpf_add_stat_strings(&data, idpf_gstrings_port_stats, IDPF_PORT_STATS_LEN); @@ -902,6 +1282,10 @@ static int idpf_get_sset_count(struct net_device *netdev, int sset) size = IDPF_PORT_STATS_LEN + (IDPF_TX_QUEUE_STATS_LEN * max_txq) + (IDPF_RX_QUEUE_STATS_LEN * max_rxq); +#ifdef CONFIG_UPLINK_PORT_STATS + if (test_bit(IDPF_VPORT_UPLINK_PORT, vport_config->flags)) + size += IDPF_PHY_PORT_STATS_LEN; +#endif /* CONFIG_UPLINK_PORT_STATS */ size += (IDPF_MAX_SEGS * 2); #ifdef IDPF_ADD_PROBES size += IDPF_PTYPE_STATS_LEN; @@ -1021,6 +1405,35 @@ static void idpf_add_empty_queue_stats(u64 **data, u16 qtype) *data += stats_len; } +#ifdef CONFIG_UPLINK_PORT_STATS +/** + * idpf_add_phy_port_stats - Copy phy_port stats into ethtool buffer + * @vport: virtual port struct + * @data: ethtool buffer to copy into + */ +static void idpf_add_phy_port_stats(struct idpf_vport *vport, u64 **data) +{ + unsigned int size = IDPF_PHY_PORT_STATS_LEN; + unsigned int start; + unsigned int i; + + /* To avoid invalid statistics values, ensure that we keep retrying + * the copy until we get a consistent value according to + * u64_stats_fetch_retry. + */ + do { + start = u64_stats_fetch_begin(&vport->port_stats.stats_sync); + for (i = 0; i < size; i++) { + idpf_add_one_ethtool_stat(&(*data)[i], + vport->port_stats.phy_port_stats, + &idpf_gstrings_phy_port_stats[i]); + } + } while (u64_stats_fetch_retry(&vport->port_stats.stats_sync, start)); + + *data += size; +} + +#endif /* CONFIG_UPLINK_PORT_STATS */ /** * idpf_add_port_stats - Copy port stats into ethtool buffer * @vport: virtual port struct @@ -1247,6 +1660,10 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, vport_config = vport->adapter->vport_config[np->vport_idx]; idpf_collect_queue_stats(vport); +#ifdef CONFIG_UPLINK_PORT_STATS + if (test_bit(IDPF_VPORT_UPLINK_PORT, vport_config->flags)) + idpf_add_phy_port_stats(vport, &data); +#endif /* CONFIG_UPLINK_PORT_STATS */ idpf_add_port_stats(vport, &data); q_grp = &vport->dflt_grp.q_grp; diff --git a/idpf/src/idpf_idc.c b/idpf/src/idpf_idc.c index bd61a6e..0e15334 100644 --- a/idpf/src/idpf_idc.c +++ b/idpf/src/idpf_idc.c @@ -3,474 +3,504 @@ #include "idpf.h" #include "idpf_virtchnl.h" +#include static DEFINE_IDA(idpf_idc_ida); +#define IDPF_IDC_MAX_ADEV_NAME_LEN 15 + /** * idpf_idc_init - Called to initialize IDC * @adapter: driver private data structure + * + * Return: 0 on success or cap not enabled, error code on failure. */ int idpf_idc_init(struct idpf_adapter *adapter) { int err; if (!idpf_is_rdma_cap_ena(adapter) || - !adapter->dev_ops.idc_ops.idc_init) + !adapter->dev_ops.idc_init) return 0; - err = adapter->dev_ops.idc_ops.idc_init(adapter); + err = adapter->dev_ops.idc_init(adapter); if (err) - dev_err(idpf_adapter_to_dev(adapter), "failed to initialize idc: %d\n", + dev_err(&adapter->pdev->dev, "failed to initialize idc: %d\n", err); return err; } /** - * idpf_idc_deinit - Called to de-initialize IDC - * @adapter: driver private data structure + * idpf_vport_adev_release - function to be mapped to aux dev's release op + * @dev: pointer to device to free */ -void idpf_idc_deinit(struct idpf_adapter *adapter) +static void idpf_vport_adev_release(struct device *dev) { - if (idpf_is_rdma_cap_ena(adapter) && - adapter->dev_ops.idc_ops.idc_deinit) - adapter->dev_ops.idc_ops.idc_deinit(adapter); + struct iidc_rdma_vport_auxiliary_dev *iadev; + + iadev = container_of(dev, struct iidc_rdma_vport_auxiliary_dev, adev.dev); + kfree(iadev); + iadev = NULL; } /** - * idpf_get_auxiliary_drv - retrieve iidc_auxiliary_drv structure - * @cdev_info: pointer to iidc_core_dev_info struct + * idpf_plug_vport_aux_dev - allocate and register a vport Auxiliary device + * @cdev_info: IDC core device info pointer + * @vdev_info: IDC vport device info pointer * - * This function has to be called with a device_lock on the - * cdev_info->adev.dev to avoid race conditions. + * Return: 0 on success or error code on failure. */ -static struct iidc_auxiliary_drv * -idpf_get_auxiliary_drv(struct iidc_core_dev_info *cdev_info) +static int idpf_plug_vport_aux_dev(struct iidc_rdma_core_dev_info *cdev_info, + struct iidc_rdma_vport_dev_info *vdev_info) { + struct iidc_rdma_vport_auxiliary_dev *iadev; + char name[IDPF_IDC_MAX_ADEV_NAME_LEN]; struct auxiliary_device *adev; + int ret; - if (!cdev_info) - return NULL; + iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); + if (!iadev) + return -ENOMEM; - adev = cdev_info->adev; - if (!adev || !adev->dev.driver) - return NULL; + adev = &iadev->adev; + vdev_info->adev = &iadev->adev; + iadev->vdev_info = vdev_info; - return container_of(adev->dev.driver, struct iidc_auxiliary_drv, - adrv.driver); -} + ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL); + if (ret < 0) { + pr_err("failed to allocate unique device ID for Auxiliary driver\n"); + goto err_ida_alloc; + } + adev->id = ret; + adev->dev.release = idpf_vport_adev_release; + adev->dev.parent = &cdev_info->pdev->dev; + sprintf(name, "%04x.rdma.vdev", cdev_info->pdev->vendor); + adev->name = name; -/** - * idpf_idc_event - Function to handle IDC event - * @rdma_data: pointer to rdma data struct - * @event_type: IDC event type - */ -void idpf_idc_event(struct idpf_rdma_data *rdma_data, - enum iidc_event_type event_type) -{ - struct iidc_core_dev_info *cdev_info = rdma_data->cdev_info; - struct iidc_auxiliary_drv *iadrv; - struct iidc_event *event; + ret = auxiliary_device_init(adev); + if (ret) + goto err_aux_dev_init; - if (!cdev_info) - /* RDMA is not enabled */ - return; + ret = auxiliary_device_add(adev); + if (ret) + goto err_aux_dev_add; - /* We do not care about other events */ - if (event_type != IIDC_EVENT_WARN_RESET && - event_type != IIDC_EVENT_AFTER_MTU_CHANGE) - return; + return 0; - event = kzalloc(sizeof(*event), GFP_KERNEL); - if (!event) - return; - set_bit(event_type, event->type); +err_aux_dev_add: + auxiliary_device_uninit(adev); +err_aux_dev_init: + ida_free(&idpf_idc_ida, adev->id); +err_ida_alloc: + vdev_info->adev = NULL; + kfree(iadev); - device_lock(&cdev_info->adev->dev); - iadrv = idpf_get_auxiliary_drv(cdev_info); - if (iadrv && iadrv->event_handler) - iadrv->event_handler(cdev_info, event); - device_unlock(&cdev_info->adev->dev); - kfree(event); + return ret; } /** - * idpf_idc_vc_receive - Used to pass the received msg over IDC - * @rdma_data: pointer to rdma data struct - * @f_id: function source id - * @msg: payload received on mailbox - * @msg_size: size of the payload + * idpf_idc_init_aux_vport_dev - initialize vport Auxiliary Device(s) + * @vport: virtual port data struct * - * This function is used by the Auxiliary Device to pass the receive mailbox - * message an Auxiliary Driver cell + * Return: 0 on success or error code on failure. */ -int idpf_idc_vc_receive(struct idpf_rdma_data *rdma_data, u32 f_id, const u8 *msg, - u16 msg_size) +static int idpf_idc_init_aux_vport_dev(struct idpf_vport *vport) { - struct iidc_core_dev_info *cdev_info; - struct iidc_auxiliary_drv *iadrv; - int err = 0; - - if (!rdma_data->cdev_info || !rdma_data->cdev_info->adev) - return -ENODEV; - - cdev_info = rdma_data->cdev_info; - - device_lock(&cdev_info->adev->dev); - iadrv = idpf_get_auxiliary_drv(cdev_info); - if (iadrv && iadrv->vc_receive) - err = iadrv->vc_receive(cdev_info, f_id, (u8 *)msg, msg_size); - device_unlock(&cdev_info->adev->dev); - if (err) - pr_err("Failed to pass receive idc msg, err %d\n", err); + struct idpf_adapter *adapter = vport->adapter; + struct iidc_rdma_vport_dev_info *vdev_info; + struct iidc_rdma_core_dev_info *cdev_info; + struct virtchnl2_create_vport *vport_msg; + int err; - return err; -} + if (vport->idx) + return 0; -/** - * idpf_idc_request_reset - Called by an Auxiliary Driver - * @cdev_info: IIDC device specific pointer - * @reset_type: function, core or other - * - * This callback function is accessed by an Auxiliary Driver to request a reset - * on the Auxiliary Device - */ -static int -idpf_idc_request_reset(struct iidc_core_dev_info *cdev_info, - enum iidc_reset_type __always_unused reset_type) -{ - struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev); + vport_msg = (struct virtchnl2_create_vport *) + adapter->vport_params_recvd[vport->idx]; - if (!idpf_is_reset_in_prog(adapter)) { - set_bit(IDPF_HR_FUNC_RESET, adapter->flags); - queue_delayed_work(adapter->vc_event_wq, - &adapter->vc_event_task, - msecs_to_jiffies(10)); - } + if (!(le16_to_cpu(vport_msg->vport_flags) & VIRTCHNL2_VPORT_ENABLE_RDMA)) + return 0; - return 0; -} + vport->vdev_info = kzalloc(sizeof(*vdev_info), GFP_KERNEL); + if (!vport->vdev_info) + return -ENOMEM; -/** - * idpf_idc_vc_async_handler - Handle async RDMA messages - * @adapter: private data struct - * @xn: transaction for message - * @ctlq_msg: message received - * - * Returns 0 on success, negative on failure. - */ -static int -idpf_idc_vc_async_handler(struct idpf_adapter *adapter, struct idpf_vc_xn *xn, - const struct idpf_ctlq_msg *ctlq_msg) -{ - if (ctlq_msg->cookie.mbx.chnl_opcode != VIRTCHNL2_OP_RDMA) - return -EINVAL; + cdev_info = vport->adapter->cdev_info; - return idpf_idc_vc_receive(&adapter->rdma_data, 0, - (u8 *)ctlq_msg->ctx.indirect.payload->va, - ctlq_msg->ctx.indirect.payload->size); -} + vdev_info = vport->vdev_info; + vdev_info->vport_id = vport->vport_id; + vdev_info->netdev = vport->netdev; + vdev_info->core_adev = cdev_info->adev; -/** - * idpf_idc_vc_send - Called by an Auxiliary Driver - * @cdev_info: IIDC device specific pointer - * @vf_id: always unused - * @msg: payload to be sent - * @msg_size: size of the payload - * - * This callback function is accessed by an Auxiliary Driver to request a send - * on the mailbox queue - */ -static int -idpf_idc_vc_send(struct iidc_core_dev_info *cdev_info, - u32 __always_unused vf_id, u8 *msg, u16 msg_size) -{ - struct idpf_vc_xn_params xn_params = { }; - struct idpf_adapter *adapter; - ssize_t reply_sz; - - if (cdev_info->cdev_info_id != IIDC_RDMA_ID) - return -EINVAL; - - if (msg_size > IDPF_CTLQ_MAX_BUF_LEN) - return -EINVAL; - - adapter = pci_get_drvdata(cdev_info->pdev); - - xn_params.vc_op = VIRTCHNL2_OP_RDMA; - xn_params.timeout_ms = idpf_get_vc_xn_default_timeout(adapter); - xn_params.send_buf.iov_base = msg; - xn_params.send_buf.iov_len = msg_size; - xn_params.async = true; - xn_params.async_handler = idpf_idc_vc_async_handler; - reply_sz = idpf_vc_xn_exec(adapter, &xn_params); - if (reply_sz < 0) { - pr_err("Failed to pass send IDC msg, err %ld\n", reply_sz); - return reply_sz; + err = idpf_plug_vport_aux_dev(cdev_info, vdev_info); + if (err) { + vport->vdev_info = NULL; + kfree(vdev_info); + return err; } return 0; } /** - * idpf_idc_vc_send_sync - synchronous version of vc_send - * @cdev_info: core device info pointer - * @send_msg: message to send - * @msg_size: size of message to send - * @recv_msg: message to populate on reception of response - * @recv_len: length of message copied into recv_msg or 0 on error + * idpf_idc_vdev_mtu_event - Function to handle IDC vport mtu change events + * @vdev_info: IDC vport device info pointer + * @event_type: type of event to pass to handler */ -static int -idpf_idc_vc_send_sync(struct iidc_core_dev_info *cdev_info, u8 *send_msg, - u16 msg_size, u8 *recv_msg, u16 *recv_len) +void idpf_idc_vdev_mtu_event(struct iidc_rdma_vport_dev_info *vdev_info, + enum iidc_rdma_event_type event_type) { - struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev); - struct idpf_vc_xn_params xn_params = { }; - ssize_t reply_sz; - u16 recv_size; - - if (!recv_msg || !recv_len || msg_size > IDPF_CTLQ_MAX_BUF_LEN) - return -EINVAL; - - recv_size = min_t(u16, *recv_len, IDPF_CTLQ_MAX_BUF_LEN); - *recv_len = 0; - xn_params.vc_op = VIRTCHNL2_OP_RDMA; - xn_params.timeout_ms = idpf_get_vc_xn_default_timeout(adapter); - xn_params.send_buf.iov_base = send_msg; - xn_params.send_buf.iov_len = msg_size; - xn_params.recv_buf.iov_base = recv_msg; - xn_params.recv_buf.iov_len = recv_size; - reply_sz = idpf_vc_xn_exec(adapter, &xn_params); - if (reply_sz < 0) - return reply_sz; - *recv_len = reply_sz; + struct iidc_rdma_vport_auxiliary_drv *iadrv; + struct iidc_rdma_event event = { }; + struct auxiliary_device *adev; - return 0; -} + if (!vdev_info) + /* RDMA is not enabled */ + return; -/** - * idpf_idc_vc_qv_map_unmap - Called by an Auxiliary Driver - * @cdev_info: IIDC device specific pointer - * @qvl_info: payload to be sent on mailbox - * @map: map or unmap - * - * Deprecated, use generic auxiliary driver messaging interface instead. - */ -static int -idpf_idc_vc_qv_map_unmap(struct iidc_core_dev_info *cdev_info, - struct iidc_qvlist_info *qvl_info, bool map) -{ - return -EOPNOTSUPP; -} + set_bit(event_type, event.type); -/* Implemented by the Auxiliary Device and called by the Auxiliary Driver */ -static const struct iidc_core_ops idc_ops = { - .request_reset = idpf_idc_request_reset, - .vc_send = idpf_idc_vc_send, - .vc_send_sync = idpf_idc_vc_send_sync, - .vc_queue_vec_map_unmap = idpf_idc_vc_qv_map_unmap, -}; + device_lock(&vdev_info->adev->dev); + adev = vdev_info->adev; + if (!adev || !adev->dev.driver) + goto unlock; + iadrv = container_of(adev->dev.driver, + struct iidc_rdma_vport_auxiliary_drv, + adrv.driver); + if (iadrv->event_handler) + iadrv->event_handler(vdev_info, &event); +unlock: + device_unlock(&vdev_info->adev->dev); +} /** - * idpf_adev_release - function to be mapped to aux dev's release op + * idpf_core_adev_release - function to be mapped to aux dev's release op * @dev: pointer to device to free */ -static void idpf_adev_release(struct device *dev) +static void idpf_core_adev_release(struct device *dev) { - struct iidc_auxiliary_dev *iadev; + struct iidc_rdma_core_auxiliary_dev *iadev; - iadev = container_of(dev, struct iidc_auxiliary_dev, adev.dev); + iadev = container_of(dev, struct iidc_rdma_core_auxiliary_dev, adev.dev); kfree(iadev); iadev = NULL; } -/* idpf_plug_aux_dev - allocate and register an Auxiliary device - * @rdma_data: pointer to rdma data struct +/** + * idpf_plug_core_aux_dev - allocate and register an Auxiliary device + * @cdev_info: IDC core device info pointer + * + * Return: 0 on success or error code on failure. */ -static int idpf_plug_aux_dev(struct idpf_rdma_data *rdma_data) +static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info) { - struct iidc_core_dev_info *cdev_info; - struct iidc_auxiliary_dev *iadev; + struct iidc_rdma_core_auxiliary_dev *iadev; + char name[IDPF_IDC_MAX_ADEV_NAME_LEN]; struct auxiliary_device *adev; - int err; - - cdev_info = rdma_data->cdev_info; - if (!cdev_info) - return -ENODEV; - - rdma_data->aux_idx = ida_alloc(&idpf_idc_ida, GFP_KERNEL); - if (rdma_data->aux_idx < 0) { - pr_err("failed to allocate unique device ID for Auxiliary driver\n"); - return -ENOMEM; - } + int ret; iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); - if (!iadev) { - err = -ENOMEM; - goto err_iadev_alloc; - } + if (!iadev) + return -ENOMEM; adev = &iadev->adev; cdev_info->adev = adev; iadev->cdev_info = cdev_info; - if (cdev_info->rdma_protocol == IIDC_RDMA_PROTOCOL_IWARP) - adev->name = IIDC_RDMA_IWARP_NAME; - else - adev->name = IIDC_RDMA_ROCE_NAME; - - adev->id = rdma_data->aux_idx; - adev->dev.release = idpf_adev_release; + ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL); + if (ret < 0) { + pr_err("failed to allocate unique device ID for Auxiliary driver\n"); + goto err_ida_alloc; + } + adev->id = ret; + adev->dev.release = idpf_core_adev_release; adev->dev.parent = &cdev_info->pdev->dev; + sprintf(name, "%04x.rdma.core", cdev_info->pdev->vendor); + adev->name = name; - err = auxiliary_device_init(adev); - if (err) + ret = auxiliary_device_init(adev); + if (ret) goto err_aux_dev_init; - err = auxiliary_device_add(adev); - if (err) + ret = auxiliary_device_add(adev); + if (ret) goto err_aux_dev_add; return 0; err_aux_dev_add: - cdev_info->adev = NULL; auxiliary_device_uninit(adev); err_aux_dev_init: + ida_free(&idpf_idc_ida, adev->id); +err_ida_alloc: + cdev_info->adev = NULL; kfree(iadev); -err_iadev_alloc: - ida_free(&idpf_idc_ida, rdma_data->aux_idx); - return err; + return ret; } -/* idpf_unplug_aux_dev - unregister and free an Auxiliary device - * @rdma_data: pointer to rdma data struct +/** + * idpf_unplug_aux_dev - unregister and free an Auxiliary device + * @adev: auxiliary device struct */ -static void idpf_unplug_aux_dev(struct idpf_rdma_data *rdma_data) +static void idpf_unplug_aux_dev(struct auxiliary_device *adev) { - struct auxiliary_device *adev; - - if (!rdma_data->cdev_info) + if (!adev) return; - ida_free(&idpf_idc_ida, rdma_data->aux_idx); - - adev = rdma_data->cdev_info->adev; auxiliary_device_delete(adev); auxiliary_device_uninit(adev); - adev = NULL; + ida_free(&idpf_idc_ida, adev->id); } /** - * idpf_idc_init_msix_data - initialize MSIX data for the cdev_info structure - * @rdma_data: pointer to rdma data struct + * idpf_idc_issue_reset_event - Function to handle reset IDC event + * @cdev_info: IDC core device info pointer */ -static void -idpf_idc_init_msix_data(struct idpf_rdma_data *rdma_data) +void idpf_idc_issue_reset_event(struct iidc_rdma_core_dev_info *cdev_info) { - struct iidc_core_dev_info *cdev_info; + enum iidc_rdma_event_type event_type = IIDC_RDMA_EVENT_WARN_RESET; + struct iidc_rdma_core_auxiliary_drv *iadrv; + struct iidc_rdma_event event = { }; + struct auxiliary_device *adev; - if (!rdma_data->msix_entries) + if (!cdev_info) + /* RDMA is not enabled */ return; - cdev_info = rdma_data->cdev_info; + set_bit(event_type, event.type); - cdev_info->msix_entries = rdma_data->msix_entries; - cdev_info->msix_count = rdma_data->num_vecs; + device_lock(&cdev_info->adev->dev); + + adev = cdev_info->adev; + if (!adev || !adev->dev.driver) + goto unlock; + + iadrv = container_of(adev->dev.driver, + struct iidc_rdma_core_auxiliary_drv, + adrv.driver); + if (iadrv->event_handler) + iadrv->event_handler(cdev_info, &event); +unlock: + device_unlock(&cdev_info->adev->dev); } /** - * idpf_idc_init_qos_info - initialialize default QoS information - * @qos_info: QoS information structure to populate + * idpf_idc_vport_dev_up - called when CORE is ready for vport aux devs + * @adapter: private data struct + * + * Return: 0 on success or error code on failure. */ -static void -idpf_idc_init_qos_info(struct iidc_qos_params *qos_info) +static int idpf_idc_vport_dev_up(struct idpf_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_alloc_vports; i++) { + struct idpf_vport *vport = adapter->vports[i]; + + if (!vport) + continue; + + if (!vport->vdev_info) + err = idpf_idc_init_aux_vport_dev(vport); + else + err = idpf_plug_vport_aux_dev(vport->adapter->cdev_info, + vport->vdev_info); + } + + return err; +} + +/** + * idpf_idc_vport_dev_down - called CORE is leaving vport aux dev support state + * @adapter: private data struct + */ +static void idpf_idc_vport_dev_down(struct idpf_adapter *adapter) { int i; - qos_info->num_apps = 0; - qos_info->num_tc = 1; + for (i = 0; i < adapter->num_alloc_vports; i++) { + struct idpf_vport *vport = adapter->vports[i]; - for (i = 0; i < IIDC_MAX_USER_PRIORITY; i++) - qos_info->up2tc[i] = 0; + if (!vport || !vport->vdev_info) + continue; - qos_info->tc_info[0].rel_bw = 100; - for (i = 1; i < IEEE_8021QAZ_MAX_TCS; i++) - qos_info->tc_info[i].rel_bw = 0; + idpf_unplug_aux_dev(vport->vdev_info->adev); + vport->vdev_info->adev = NULL; + } } /** - * idpf_idc_init_aux_device - initialize Auxiliary Device(s) - * @rdma_data: pointer to rdma data struct - * @ftype: function type + * idpf_idc_vport_dev_ctrl - Called by an Auxiliary Driver + * @cdev_info: IDC core device info pointer + * @up: RDMA core driver status + * + * This callback function is accessed by an Auxiliary Driver to indicate + * whether core driver is ready to support vport driver load or if vport + * drivers need to be taken down. + * + * Return: 0 on success or error code on failure. */ -int -idpf_idc_init_aux_device(struct idpf_rdma_data *rdma_data, - enum iidc_function_type ftype) +int idpf_idc_vport_dev_ctrl(struct iidc_core_dev_info *cdev_info, bool up) { - struct iidc_core_dev_info *cdev_info; - struct idpf_adapter *adapter; - int err; + struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev); - /* structure layout needed for container_of's looks like: - * iidc_auxiliary_dev (container_of super-struct for adev) - * |--> auxiliary_device - * |--> *iidc_core_dev_info (pointer from cdev_info struct) - * - * The iidc_auxiliary_device has a lifespan as long as it - * is on the bus. Once removed it will be freed and a new - * one allocated if needed to re-add. - */ - rdma_data->cdev_info = kzalloc(sizeof(struct iidc_core_dev_info), - GFP_KERNEL); - if (!rdma_data->cdev_info) { - err = -ENOMEM; - goto err_cdev_info_alloc; + if (up) + return idpf_idc_vport_dev_up(adapter); + + idpf_idc_vport_dev_down(adapter); + + return 0; +} +EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl); + +/** + * idpf_idc_request_reset - Called by an Auxiliary Driver + * @cdev_info: IDC core device info pointer + * @reset_type: function, core or other + * + * This callback function is accessed by an Auxiliary Driver to request a reset + * on the Auxiliary Device. + * + * Return: 0 on success or error code on failure. + */ +int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info, + enum iidc_rdma_reset_type __always_unused reset_type) +{ + struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev); + + if (!idpf_is_reset_in_prog(adapter)) { + set_bit(IDPF_HR_FUNC_RESET, adapter->flags); + queue_delayed_work(adapter->vc_event_wq, + &adapter->vc_event_task, + msecs_to_jiffies(10)); } - adapter = container_of(rdma_data, struct idpf_adapter, rdma_data); + return 0; +} +EXPORT_SYMBOL_GPL(idpf_idc_request_reset); + +/** + * idpf_idc_init_msix_data - initialize MSIX data for the cdev_info structure + * @adapter: driver private data structure + */ +static void +idpf_idc_init_msix_data(struct idpf_adapter *adapter) +{ + struct iidc_rdma_core_dev_info *cdev_info; + struct iidc_rdma_priv_dev_info *privd; + + if (!adapter->rdma_msix_entries) + return; + + cdev_info = adapter->cdev_info; + privd = (struct iidc_rdma_priv_dev_info *)cdev_info->iidc_priv; + + privd->msix_entries = adapter->rdma_msix_entries; + privd->msix_count = adapter->num_rdma_msix_entries; +} + +/** + * idpf_idc_init_aux_core_dev - initialize Auxiliary Device(s) + * @adapter: driver private data structure + * @ftype: PF or VF + * + * Return: 0 on success or error code on failure. + */ +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter, + enum iidc_function_type ftype) +{ + struct iidc_rdma_core_dev_info *cdev_info; + struct iidc_rdma_priv_dev_info *privd; + int err, i; + + adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL); + if (!adapter->cdev_info) + return -ENOMEM; + cdev_info = adapter->cdev_info; - cdev_info = rdma_data->cdev_info; - cdev_info->hw_addr = (u8 __iomem *)adapter->hw.hw_addr; + privd = kzalloc(sizeof(*privd), GFP_KERNEL); + if (!privd) { + err = -ENOMEM; + goto err_privd_alloc; + } + + cdev_info->iidc_priv = privd; + cdev_info->pdev = adapter->pdev; cdev_info->ver.major = IIDC_MAJOR_VER; cdev_info->ver.minor = IIDC_MINOR_VER; - cdev_info->ftype = ftype; - cdev_info->vport_id = adapter->vports[0]->vport_id; - cdev_info->netdev = adapter->vports[0]->netdev; - cdev_info->pdev = adapter->pdev; - cdev_info->ops = &idc_ops; - cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_IWARP; - cdev_info->cdev_info_id = IIDC_RDMA_ID; + cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2; + privd->ftype = ftype; - idpf_idc_init_qos_info(&cdev_info->qos_info); - idpf_idc_init_msix_data(rdma_data); + privd->mapped_mem_regions = kcalloc(adapter->hw.num_lan_regs, + sizeof(struct iidc_rdma_lan_mapped_mem_region), + GFP_KERNEL); + if (!privd->mapped_mem_regions) { + err = -ENOMEM; + goto err_plug_aux_dev; + } + + privd->num_memory_regions = cpu_to_le16(adapter->hw.num_lan_regs); + for (i = 0; i < adapter->hw.num_lan_regs; i++) { + privd->mapped_mem_regions[i].region_addr = + (u8 __iomem *)adapter->hw.lan_regs[i].vaddr; + privd->mapped_mem_regions[i].size = + cpu_to_le64(adapter->hw.lan_regs[i].addr_len); + privd->mapped_mem_regions[i].start_offset = + cpu_to_le64(adapter->hw.lan_regs[i].addr_start); + } - err = idpf_plug_aux_dev(rdma_data); + idpf_idc_init_msix_data(adapter); + + err = idpf_plug_core_aux_dev(cdev_info); if (err) - goto err_plug_aux_dev; + goto err_free_mem_regions; return 0; +err_free_mem_regions: + kfree(privd->mapped_mem_regions); + privd->mapped_mem_regions = NULL; err_plug_aux_dev: - kfree(rdma_data->cdev_info); - rdma_data->cdev_info = NULL; -err_cdev_info_alloc: - memset(rdma_data, 0, sizeof(*rdma_data)); + kfree(privd); +err_privd_alloc: + kfree(cdev_info); + adapter->cdev_info = NULL; return err; } /** - * idpf_idc_deinit_aux_device - de-initialize Auxiliary Device(s) - * @adapter: driver private data structure + * idpf_idc_deinit_core_aux_device - de-initialize Auxiliary Device(s) + * @cdev_info: IDC core device info pointer */ -void idpf_idc_deinit_aux_device(struct idpf_adapter *adapter) +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info) { - struct idpf_rdma_data *rdma_data = &adapter->rdma_data; + struct iidc_rdma_priv_dev_info *privd; + + if (!cdev_info) + return; + + idpf_unplug_aux_dev(cdev_info->adev); + + privd = (struct iidc_rdma_priv_dev_info *)cdev_info->iidc_priv; + kfree(privd->mapped_mem_regions); + kfree(privd); + kfree(cdev_info); +} + +/** + * idpf_idc_deinit_vport_aux_device - de-initialize Auxiliary Device(s) + * @vdev_info: IDC vport device info pointer + */ +void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info) +{ + if (!vdev_info) + return; + + idpf_unplug_aux_dev(vdev_info->adev); - idpf_unplug_aux_dev(rdma_data); - kfree(rdma_data->cdev_info); - memset(rdma_data, 0, sizeof(*rdma_data)); + kfree(vdev_info); } diff --git a/idpf/src/idpf_lan_txrx.h b/idpf/src/idpf_lan_txrx.h index 194e0af..b8bd341 100644 --- a/idpf/src/idpf_lan_txrx.h +++ b/idpf/src/idpf_lan_txrx.h @@ -186,7 +186,7 @@ enum idpf_tx_base_desc_cmd_bits { struct idpf_base_tx_desc { __le64 buf_addr; /* Address of descriptor's data buf */ __le64 qw1; /* type_cmd_offset_bsz_l2tag1 */ -};/* read used with buffer queues*/ +};/* read used with buffer queues */ struct idpf_splitq_tx_compl_desc { /* qid=[10:0] comptype=[13:11] rsvd=[14] gen=[15] */ @@ -197,7 +197,7 @@ struct idpf_splitq_tx_compl_desc { } q_head_compl_tag; u8 ts[3]; u8 rsvd; /* Reserved */ -};/* writeback used with completion queues*/ +};/* writeback used with completion queues */ /* Context descriptors */ struct idpf_base_tx_ctx_desc { diff --git a/idpf/src/idpf_lib.c b/idpf/src/idpf_lib.c index 01614ff..c0cb2e4 100644 --- a/idpf/src/idpf_lib.c +++ b/idpf/src/idpf_lib.c @@ -63,15 +63,12 @@ void idpf_deinit_vector_stack(struct idpf_adapter *adapter) /** * idpf_mb_intr_rel_irq - Free the IRQ association with the OS * @adapter: adapter structure - * - * This will also disable interrupt mode and queue up mailbox task. Mailbox - * task will reschedule itself if not in interrupt mode. */ -static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter) +void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter) { - clear_bit(IDPF_MB_INTR_MODE, adapter->flags); + if (!test_and_clear_bit(IDPF_MB_INTR_MODE, adapter->flags)) + return; kfree(free_irq(adapter->msix_entries[0].vector, adapter)); - queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); kfree(adapter->mb_vector.name); adapter->mb_vector.name = NULL; } @@ -87,13 +84,21 @@ void idpf_intr_rel(struct idpf_adapter *adapter) idpf_mb_intr_rel_irq(adapter); pci_free_irq_vectors(adapter->pdev); - + /* Need the mbx_task in polling mode to send dealloc vectors message + * when not called during a reset. + */ + if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) + queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); idpf_send_dealloc_vectors_msg(adapter); idpf_deinit_vector_stack(adapter); kfree(adapter->msix_entries); adapter->msix_entries = NULL; - kfree(adapter->rdma_data.msix_entries); - adapter->rdma_data.msix_entries = NULL; + kfree(adapter->rdma_msix_entries); + adapter->rdma_msix_entries = NULL; +#ifdef CONFIG_RCA_SUPPORT + kfree(adapter->rca_msix_entries); + adapter->rca_msix_entries = NULL; +#endif /* CONFIG_RCA_SUPPORT */ } /** @@ -114,7 +119,7 @@ static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data) /* ASQ may not be set */ if (adapter->hw.asq) { - if (!(readl(idpf_get_reg_addr(adapter, adapter->hw.asq->reg.len)) & + if (!(readl(idpf_get_mbx_reg_addr(adapter, adapter->hw.asq->reg.len)) & adapter->hw.asq->reg.len_ena_mask)) { set_bit(IDPF_CORER_IN_PROG, adapter->flags); reinit_completion(&adapter->corer_done); @@ -318,7 +323,7 @@ int idpf_intr_req(struct idpf_adapter *adapter) u16 num_lan_vecs, min_lan_vecs, num_rdma_vecs = 0, min_rdma_vecs = 0; u16 default_vports = idpf_get_default_vports(adapter); int num_q_vecs, total_vecs, num_vec_ids; - int min_vectors, v_actual, err; + int min_vectors, actual_vecs, err; unsigned int vector; u16 *vecids; int i; @@ -354,37 +359,51 @@ int idpf_intr_req(struct idpf_adapter *adapter) min_lan_vecs = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports; min_vectors = min_lan_vecs + min_rdma_vecs; - v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors, - total_vecs, PCI_IRQ_MSIX); - if (v_actual < min_vectors) { - dev_err(idpf_adapter_to_dev(adapter), "Failed to allocate minimum MSIX vectors required: %d\n", - v_actual); - err = -EAGAIN; +#ifdef CONFIG_RCA_SUPPORT + if (idpf_is_rca_enabled(adapter)) + min_vectors += IDPF_MIN_RCA_VEC; +#endif /* CONFIG_RCA_SUPPORT */ + actual_vecs = pci_alloc_irq_vectors(adapter->pdev, min_vectors, + total_vecs, PCI_IRQ_MSIX); + if (actual_vecs < 0) { + dev_err(&adapter->pdev->dev, "Failed to allocate minimum MSIX vectors required: %d\n", + min_vectors); + err = actual_vecs; goto send_dealloc_vecs; } - num_lan_vecs = v_actual - num_rdma_vecs; - if (idpf_is_rdma_cap_ena(adapter)) { - if (v_actual < total_vecs) { - dev_warn(idpf_adapter_to_dev(adapter), - "Warning: not enough vectors available. Defaulting to minimum for RDMA and remaining for LAN.\n"); + if (actual_vecs < total_vecs) { + dev_warn(&adapter->pdev->dev, + "Warning: %d vectors requested, only %d available. Defaulting to minimum (%d) for RDMA and remaining for LAN.\n", + total_vecs, actual_vecs, IDPF_MIN_RDMA_VEC); num_rdma_vecs = min_rdma_vecs; - /* Reset num_lan_vecs to account for updated - * num_rdma_vecs - */ - num_lan_vecs = v_actual - min_rdma_vecs; } - adapter->rdma_data.msix_entries = kcalloc(num_rdma_vecs, - sizeof(struct msix_entry), - GFP_KERNEL); - if (!adapter->rdma_data.msix_entries) { + adapter->rdma_msix_entries = kcalloc(num_rdma_vecs, + sizeof(struct msix_entry), + GFP_KERNEL); + if (!adapter->rdma_msix_entries) { err = -ENOMEM; goto free_irq; } +#ifdef CONFIG_RCA_SUPPORT + + if (idpf_is_rca_enabled(adapter)) { + num_lan_vecs -= IDPF_MIN_RCA_VEC; + + adapter->rca_msix_entries = kcalloc(IDPF_MIN_RDMA_VEC, + sizeof(struct msix_entry), + GFP_KERNEL); + if (!adapter->rca_msix_entries) { + err = -ENOMEM; + goto rca_msix_alloc_fail; + } + } +#endif /* CONFIG_RCA_SUPPORT */ } + num_lan_vecs = actual_vecs - num_rdma_vecs; adapter->msix_entries = kcalloc(num_lan_vecs, sizeof(struct msix_entry), GFP_KERNEL); @@ -395,15 +414,15 @@ int idpf_intr_req(struct idpf_adapter *adapter) adapter->mb_vector.v_idx = le16_to_cpu(adapter->caps.mailbox_vector_id); - vecids = kcalloc(v_actual, sizeof(u16), GFP_KERNEL); + vecids = kcalloc(actual_vecs, sizeof(u16), GFP_KERNEL); if (!vecids) { err = -ENOMEM; goto free_msix; } - num_vec_ids = idpf_get_vec_ids(adapter, vecids, v_actual, + num_vec_ids = idpf_get_vec_ids(adapter, vecids, actual_vecs, &adapter->req_vec_chunks->vchunks); - if (num_vec_ids < v_actual) { + if (num_vec_ids < actual_vecs) { err = -EINVAL; goto free_vecids; } @@ -414,18 +433,30 @@ int idpf_intr_req(struct idpf_adapter *adapter) pci_irq_vector(adapter->pdev, vector); } for (i = 0; i < num_rdma_vecs; vector++, i++) { - adapter->rdma_data.msix_entries[i].entry = vecids[vector]; - adapter->rdma_data.msix_entries[i].vector = + adapter->rdma_msix_entries[i].entry = vecids[vector]; + adapter->rdma_msix_entries[i].vector = pci_irq_vector(adapter->pdev, vector); } +#ifdef CONFIG_RCA_SUPPORT + if (idpf_is_rdma_cap_ena(adapter) && idpf_is_rca_enabled(adapter)) { + for (i = 0; i < IDPF_MIN_RCA_VEC; vector++, i++) { + adapter->rca_msix_entries[i].entry = vecids[vector]; + adapter->rca_msix_entries[i].vector = + pci_irq_vector(adapter->pdev, vector); + } + adapter->num_rca_msix_entries = IDPF_MIN_RCA_VEC; + } +#endif /* CONFIG_RCA_SUPPORT */ - adapter->rdma_data.num_vecs = num_rdma_vecs; + adapter->num_rdma_msix_entries = num_rdma_vecs; /* 'num_avail_msix' is used to distribute excess vectors to the vports * after considering the minimum vectors required per each default * vport */ adapter->num_avail_msix = num_lan_vecs - min_lan_vecs; adapter->num_msix_entries = num_lan_vecs; + if (idpf_is_rdma_cap_ena(adapter)) + adapter->num_rdma_msix_entries = num_rdma_vecs; /* Fill MSIX vector lifo stack with vector indexes */ err = idpf_init_vector_stack(adapter); @@ -448,8 +479,13 @@ int idpf_intr_req(struct idpf_adapter *adapter) kfree(adapter->msix_entries); adapter->msix_entries = NULL; free_rdma_msix: - kfree(adapter->rdma_data.msix_entries); - adapter->rdma_data.msix_entries = NULL; +#ifdef CONFIG_RCA_SUPPORT + kfree(adapter->rca_msix_entries); + adapter->rca_msix_entries = NULL; +rca_msix_alloc_fail: +#endif /* CONFIG_RCA_SUPPORT */ + kfree(adapter->rdma_msix_entries); + adapter->rdma_msix_entries = NULL; free_irq: pci_free_irq_vectors(adapter->pdev); send_dealloc_vecs: @@ -458,6 +494,29 @@ int idpf_intr_req(struct idpf_adapter *adapter) return err; } +/** + * idpf_del_all_flow_steer_filters - Delete all flow steer filters in list + * @vport: main vport struct + * + * Takes flow_steer_list_lock spinlock. Deletes all filters + */ +static void idpf_del_all_flow_steer_filters(struct idpf_vport *vport) +{ + struct idpf_vport_config *vport_config; + struct idpf_fsteer_fltr *f, *ftmp; + + vport_config = vport->adapter->vport_config[vport->idx]; + + spin_lock_bh(&vport_config->flow_steer_list_lock); + list_for_each_entry_safe(f, ftmp, &vport_config->user_config.flow_steer_list, + list) { + list_del(&f->list); + kfree(f); + } + vport_config->user_config.num_fsteer_fltrs = 0; + spin_unlock_bh(&vport_config->flow_steer_list_lock); +} + /** * idpf_find_mac_filter - Search filter list for specific mac filter * @vconfig: Vport config structure @@ -744,21 +803,63 @@ static int idpf_init_mac_addr(struct idpf_vport *vport, return 0; } -/** - * idpf_device_detach - Mark device as removed on reset. This will help reduce - * noise from kernel callbacks. - * @adapter: private data struct - */ -void idpf_device_detach(struct idpf_adapter *adapter) +void idpf_detach_and_close(struct idpf_adapter *adapter) { - int i; + int max_vports = adapter->max_vports; - rtnl_lock(); - for (i = 0; i < adapter->max_vports; i++) { - if (adapter->netdevs[i]) - netif_device_detach(adapter->netdevs[i]); + for (int i = 0; i < max_vports; i++) { + struct net_device *netdev = adapter->netdevs[i]; + + /* If the interface is in detached state, that means the + * previous reset was not handled successfully for this + * vport. + */ + if (!netif_device_present(netdev)) + continue; + + /* Hold RTNL to protect racing with callbacks */ + rtnl_lock(); + netif_device_detach(netdev); + if (netif_running(netdev)) { + set_bit(IDPF_VPORT_UP_REQUESTED, + adapter->vport_config[i]->flags); + dev_close(netdev); + } + rtnl_unlock(); + } +} + +void idpf_attach_and_open(struct idpf_adapter *adapter) +{ + int max_vports = adapter->max_vports; + + for (int i = 0; i < max_vports; i++) { + struct idpf_vport *vport = adapter->vports[i]; + struct idpf_vport_config *vport_config; + struct net_device *netdev; + + /* In case of a critical error in the init task, the vport + * will be freed. Only continue to restore the netdevs + * if the vport is allocated. + */ + if (!vport) + continue; + + /* No need for RTNL on attach as this function is called + * following detach and dev_close(). We do take RTNL for + * dev_open() below as it can race with external callbacks + * following the call to netif_device_attach(). + */ + netdev = adapter->netdevs[i]; + netif_device_attach(netdev); + vport_config = adapter->vport_config[vport->idx]; + if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, + vport_config->flags)) { + rtnl_lock(); + dev_open(netdev, NULL); + rtnl_unlock(); + } } - rtnl_unlock(); } /** @@ -886,6 +987,10 @@ static int idpf_cfg_netdev(struct idpf_vport *vport) if (idpf_is_cap_ena_all(adapter, IDPF_RSS_CAPS, IDPF_CAP_RSS)) dflt_features |= NETIF_F_RXHASH; + if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, + VIRTCHNL2_CAP_FLOW_STEER) && + idpf_vport_is_cap_ena(vport, VIRTCHNL2_VPORT_SIDEBAND_FLOW_STEER)) + dflt_features |= NETIF_F_NTUPLE; if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_TX_CSUM_L4V4)) csum_offloads |= NETIF_F_IP_CSUM; if (idpf_is_cap_ena_all(adapter, IDPF_CSUM_CAPS, IDPF_CAP_TX_CSUM_L4V6)) @@ -981,29 +1086,6 @@ static void idpf_netdev_stop(struct net_device *netdev) netif_tx_disable(netdev); } -/** - * idpf_netdev_stop_all - Stop all traffic on all netdevs - * @adapter: private data struct - * - * In the case of PFR, we have a small window to stop queueing up - * traffic before we start triggering tx timeouts on queues that got - * yanked out from under us. We can't afford to timeout on all the - * virtchnl messages or wait for cancelling delayed work before - * stopping traffic. Stop traffic on all vports first, then try to - * clean up any dangling resources. - */ -void idpf_netdev_stop_all(struct idpf_adapter *adapter) -{ - int i; - - if (!adapter->vports) - return; - - for (i = 0; i < adapter->max_vports; i++) - if (adapter->vports[i]) - idpf_netdev_stop(adapter->vports[i]->netdev); -} - /** * idpf_vport_stop - Disable a vport * @vport: vport to disable @@ -1016,8 +1098,6 @@ static void idpf_vport_stop(struct idpf_vport *vport) if (!test_and_clear_bit(IDPF_VPORT_UP, np->state)) return; - /* Make sure soft reset has finished */ - cancel_work_sync(&vport->finish_reset_task); idpf_netdev_stop(vport->netdev); if (!test_bit(IDPF_CORER_IN_PROG, vport->adapter->flags)) { @@ -1118,6 +1198,10 @@ static void idpf_vport_rel(struct idpf_vport *vport) /* Release all the allocated vectors on the stack */ idpf_vport_dealloc_vec_indexes(vport, &vport->dflt_grp); +#ifdef CONFIG_UPLINK_PORT_STATS + kfree(vport->port_stats.phy_port_stats); + +#endif /* CONFIG_UPLINK_PORT_STATS */ kfree(adapter->vport_params_recvd[idx]); adapter->vport_params_recvd[idx] = NULL; if (adapter->vport_config[idx]) { @@ -1153,7 +1237,7 @@ static void idpf_rx_init_buf_tail(struct idpf_q_grp *q_grp) struct idpf_queue *q = &grp->splitq.bufq_sets[j].bufq; - writel(q->next_to_alloc, q->tail); + writel(q->next_to_alloc, q->tail); } } else { for (j = 0; j < grp->singleq.num_rxq; j++) { @@ -1181,19 +1265,21 @@ static void idpf_vport_dealloc(struct idpf_vport *vport) struct idpf_adapter *adapter = vport->adapter; unsigned int i = vport->idx; - idpf_deinit_mac_addr(vport); + idpf_idc_deinit_vport_aux_device(vport->vdev_info); - idpf_vport_cfg_lock(adapter); - idpf_vport_stop(vport); - idpf_vport_cfg_unlock(adapter); + idpf_deinit_mac_addr(vport); - if (!vport->idx) - idpf_idc_deinit(adapter); + if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) { + idpf_vport_cfg_lock(adapter); + idpf_vport_stop(vport); + idpf_vport_cfg_unlock(adapter); - if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) idpf_decfg_netdev(vport); - if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) + } + if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) { idpf_del_user_cfg_data(vport); + idpf_del_all_flow_steer_filters(vport); + } if (adapter->netdevs[i]) { struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]); @@ -1471,6 +1557,12 @@ void idpf_statistics_task(struct work_struct *work) if (!vport) continue; +#ifdef CONFIG_UPLINK_PORT_STATS + if (test_bit(IDPF_VPORT_UPLINK_PORT, + adapter->vport_config[i]->flags)) + idpf_send_get_port_stats_msg(vport); + else +#endif /* CONFIG_UPLINK_PORT_STATS */ idpf_send_get_stats_msg(vport); } @@ -1833,32 +1925,27 @@ void idpf_init_task(struct work_struct *work) goto unwind_vports; } + err = idpf_send_get_rx_ptype_msg(vport); + if (err) + goto unwind_vports; + index = vport->idx; vport_config = adapter->vport_config[index]; init_waitqueue_head(&vport->sw_marker_wq); spin_lock_init(&vport_config->mac_filter_list_lock); + spin_lock_init(&vport_config->flow_steer_list_lock); INIT_LIST_HEAD(&vport_config->user_config.mac_filter_list); + INIT_LIST_HEAD(&vport_config->user_config.flow_steer_list); err = idpf_check_supported_desc_ids(vport); if (err) { dev_err(&pdev->dev, "failed to get required descriptor ids\n"); - goto cfg_netdev_err; + goto unwind_vports; } if (idpf_cfg_netdev(vport)) - goto cfg_netdev_err; - - err = idpf_send_get_rx_ptype_msg(vport); - if (err) - goto handle_err; - - - if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags)) { - idpf_vport_cfg_lock(adapter); - idpf_vport_open(vport); - idpf_vport_cfg_unlock(adapter); - } + goto unwind_vports; /* Spawn and return 'idpf_init_task' work queue until all the * default vports are created @@ -1871,33 +1958,27 @@ void idpf_init_task(struct work_struct *work) } for (index = 0; index < adapter->max_vports; index++) { - struct idpf_vport_config *vport_config = adapter->vport_config[index]; struct net_device *netdev = adapter->netdevs[index]; + struct idpf_vport_config *vport_config; + + vport_config = adapter->vport_config[index]; - if (!netdev) + if (!netdev || + test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) continue; - if (!test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) { - err = register_netdev(netdev); - if (err) { - dev_err(&pdev->dev, "failed to register netdev for vport %d: %pe\n", - index, ERR_PTR(err)); - continue; - } - set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags); - } else { - netif_device_attach(netdev); + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "failed to register netdev for vport %d: %pe\n", + index, ERR_PTR(err)); + continue; } + set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags); } - err = idpf_idc_init(adapter); - if (err) - goto handle_err; - - /* As all the required vports are created, clear the reset flag - * unconditionally here in case we were in reset and the link was down. - */ + /* Clear the reset and load bits as all vports are created */ clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); + clear_bit(IDPF_HR_DRV_LOAD, adapter->flags); if (!IS_SILICON_DEVICE(adapter->hw.subsystem_device_id)) return; /* Start the statistics task now */ @@ -1905,11 +1986,6 @@ void idpf_init_task(struct work_struct *work) return; -handle_err: - idpf_decfg_netdev(vport); -cfg_netdev_err: - idpf_vport_rel(vport); - adapter->vports[index] = NULL; unwind_vports: if (default_vport) { for (index = 0; index < adapter->max_vports; index++) { @@ -1917,6 +1993,16 @@ void idpf_init_task(struct work_struct *work) idpf_vport_dealloc(adapter->vports[index]); } } + + /* Cleanup after vc_core_init, which has no way of knowing the + * init task failed on driver load. + */ + if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { + cancel_delayed_work_sync(&adapter->serv_task); + cancel_delayed_work_sync(&adapter->mbx_task); + } + idpf_ptp_release(adapter); + clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); } @@ -2095,27 +2181,6 @@ int idpf_check_reset_complete(struct idpf_adapter *adapter) return -EBUSY; } -/** - * idpf_set_vport_state - Set the vport state to be after the reset - * @adapter: Driver specific private structure - */ -void idpf_set_vport_state(struct idpf_adapter *adapter) -{ - u16 i; - - for (i = 0; i < adapter->max_vports; i++) { - struct idpf_netdev_priv *np; - - if (!adapter->netdevs[i]) - continue; - - np = netdev_priv(adapter->netdevs[i]); - if (test_bit(IDPF_VPORT_UP, np->state)) - set_bit(IDPF_VPORT_UP_REQUESTED, - adapter->vport_config[i]->flags); - } -} - /** * idpf_wait_on_reset_detection - Wait until reset has been detected * @adapter: Driver specific private structure @@ -2154,19 +2219,16 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter) struct device *dev = idpf_adapter_to_dev(adapter); int err; + idpf_detach_and_close(adapter); idpf_vport_init_lock(adapter); dev_info(dev, "Device HW Reset initiated\n"); - /* Avoid TX hangs on reset */ - idpf_netdev_stop_all(adapter); - idpf_device_detach(adapter); - /* Prepare for reset */ - if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { + if (test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD); } else if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags)) { - idpf_idc_event(&adapter->rdma_data, IIDC_EVENT_WARN_RESET); + idpf_idc_issue_reset_event(adapter->cdev_info); if (!idpf_is_reset_detected(adapter)) { reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET); @@ -2176,7 +2238,6 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter) goto unlock_mutex; } } - idpf_set_vport_state(adapter); } else { dev_err(dev, "Unhandled hard reset cause\n"); err = -EBADRQC; @@ -2207,6 +2268,12 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter) unlock_mutex: idpf_vport_init_unlock(adapter); + if (!err) { + idpf_attach_and_open(adapter); + /* Wait until all vports are created to init RDMA CORE AUX */ + err = idpf_idc_init(adapter); + } + return err; } @@ -2223,29 +2290,19 @@ void idpf_vc_event_task(struct work_struct *work) if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) return; - if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags) || - test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { - set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); - idpf_init_hard_reset(adapter); - } -} + if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags)) + goto func_reset; -/** - * idpf_finish_soft_reset - Delayed task to finish vport soft reset - * @work: work_struct handle - * - * All work that needs to be done __without__ RTNL. - */ -void idpf_finish_soft_reset(struct work_struct *work) -{ - struct idpf_vport *vport; + if (test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) + goto drv_load; - vport = container_of(work, struct idpf_vport, finish_reset_task); + return; - if (test_and_clear_bit(IDPF_VPORT_MTU_CHANGED, vport->flags)) { - idpf_idc_event(&vport->adapter->rdma_data, - IIDC_EVENT_AFTER_MTU_CHANGE); - } +func_reset: + idpf_vc_xn_shutdown(adapter->vcxn_mngr); +drv_load: + set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); + idpf_init_hard_reset(adapter); } /** @@ -2304,6 +2361,9 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, break; case IDPF_SR_Q_SCH_CHANGE: case IDPF_SR_MTU_CHANGE: + idpf_idc_vdev_mtu_event(vport->vdev_info, + IIDC_RDMA_EVENT_BEFORE_MTU_CHANGE); + break; case IDPF_SR_RSC_CHANGE: case IDPF_SR_HSPLIT_CHANGE: #ifdef HAVE_XDP_SUPPORT @@ -2370,14 +2430,7 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, if (vport_is_up) err = idpf_vport_open(vport); - if (!err && !vport->idx && reset_cause == IDPF_SR_MTU_CHANGE) { - set_bit(IDPF_VPORT_MTU_CHANGED, vport->flags); - queue_work(system_unbound_wq, &vport->finish_reset_task); - } - - kfree(new_vport); - - return err; + goto free_vport; err_reset: q_grp = &vport->dflt_grp.q_grp; @@ -2390,6 +2443,10 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, free_vport: kfree(new_vport); + if (reset_cause == IDPF_SR_MTU_CHANGE) + idpf_idc_vdev_mtu_event(vport->vdev_info, + IIDC_RDMA_EVENT_AFTER_MTU_CHANGE); + return err; } @@ -2950,32 +3007,30 @@ static int idpf_setup_tc(struct net_device *netdev, enum tc_setup_type type, void *type_data) { struct idpf_adapter *adapter = idpf_netdev_to_adapter(netdev); - struct idpf_vport *vport; int err = 0; - idpf_vport_cfg_lock(adapter); - vport = idpf_netdev_to_vport(netdev); - switch (type) { #ifdef HAVE_ETF_SUPPORT - case TC_SETUP_QDISC_ETF: - if (!idpf_is_queue_model_split(vport->dflt_grp.q_grp.txq_model)) { + case TC_SETUP_QDISC_ETF: { + struct idpf_vport *vport; + + idpf_vport_cfg_lock(adapter); + vport = idpf_netdev_to_vport(netdev); + + if (!idpf_is_queue_model_split(vport->dflt_grp.q_grp.txq_model)) err = -EOPNOTSUPP; - goto vport_ctrl_unlock; - } - err = idpf_offload_txtime(vport, type_data); + else + err = idpf_offload_txtime(vport, type_data); + + idpf_vport_cfg_unlock(adapter); break; + } #endif /* HAVE_ETF_SUPPORT */ default: err = -EOPNOTSUPP; break; } -#ifdef HAVE_ETF_SUPPORT -vport_ctrl_unlock: -#endif /* HAVE_ETF_SUPPORT */ - idpf_vport_cfg_unlock(adapter); - return err; } diff --git a/idpf/src/idpf_main.c b/idpf/src/idpf_main.c index a7c8f4b..736a49a 100644 --- a/idpf/src/idpf_main.c +++ b/idpf/src/idpf_main.c @@ -38,7 +38,8 @@ static void idpf_deinit_iommu_bypass(struct idpf_adapter *adapter) adapter->iommu_byp.bypass_size); if (adapter->iommu_byp.ddev) { struct platform_device *ldev = - adapter->iommu_byp.ddev->platform_data; + container_of(adapter->iommu_byp.ddev, + struct platform_device, dev); platform_device_unregister(ldev); } } @@ -67,7 +68,6 @@ static int idpf_init_iommu_bypass(struct idpf_adapter *adapter, goto iommu_bypass_fail; adapter->iommu_byp.ddev = &ldev->dev; - adapter->iommu_byp.ddev->platform_data = ldev; adapter->iommu_byp.ddev->cma_area = pdev->dev.cma_area; adapter->iommu_byp.ddev->dma_coherent = true; @@ -87,7 +87,8 @@ static int idpf_init_iommu_bypass(struct idpf_adapter *adapter, err = iommu_map(iodom, adapter->iommu_byp.bypass_iova_addr, adapter->iommu_byp.bypass_phys_addr, adapter->iommu_byp.bypass_size, - IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE); + IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE, + GFP_KERNEL); if (err) goto iommu_bypass_fail; dev_info(&pdev->dev, @@ -201,9 +202,6 @@ static void idpf_remove(struct pci_dev *pdev) #ifdef HAVE_PCI_ENABLE_PCIE_ERROR_REPORTING pci_disable_pcie_error_reporting(pdev); #endif /* HAVE_PCI_ENABLE_PCIE_ERROR_REPORTING */ - iounmap(adapter->hw.hw_addr); - if (adapter->hw.hw_addr_region2) - iounmap(adapter->hw.hw_addr_region2); pci_release_mem_regions(pdev); #ifdef CONFIG_IOMMU_BYPASS @@ -227,9 +225,15 @@ static void idpf_shutdown(struct pci_dev *pdev) { struct idpf_adapter *adapter = pci_get_drvdata(pdev); + set_bit(IDPF_REMOVE_IN_PROG, adapter->flags); + cancel_delayed_work_sync(&adapter->serv_task); cancel_delayed_work_sync(&adapter->vc_event_task); + + idpf_vport_init_lock(adapter); idpf_vc_core_deinit(adapter); + idpf_vport_init_unlock(adapter); + idpf_deinit_dflt_mbx(adapter); if (system_state == SYSTEM_POWER_OFF) @@ -244,38 +248,42 @@ static void idpf_shutdown(struct pci_dev *pdev) */ static int idpf_cfg_hw(struct idpf_adapter *adapter) { - u64 region2_start = adapter->dev_ops.bar0_region2_start; + resource_size_t res_start, mbx_start, rstat_start; struct pci_dev *pdev = adapter->pdev; struct idpf_hw *hw = &adapter->hw; - resource_size_t res_start; + struct device *dev = &pdev->dev; long len; res_start = pci_resource_start(pdev, 0); - len = adapter->dev_ops.bar0_region1_size; - hw->hw_addr = ioremap(res_start, len); - if (!hw->hw_addr) { - dev_info(&pdev->dev, "ioremap(0x%04llx) region1 failed:\n", - res_start); - return -EIO; + + /* Map mailbox space for virtchnl communication */ + mbx_start = res_start + adapter->dev_ops.static_reg_info[0].start; + len = resource_size(&adapter->dev_ops.static_reg_info[0]); + hw->mbx.vaddr = devm_ioremap(dev, mbx_start, len); + if (!hw->mbx.vaddr) { + pci_err(pdev, "failed to allocate BAR0 mbx region\n"); + + return -ENOMEM; } - hw->hw_addr_len = len; + hw->mbx.addr_start = adapter->dev_ops.static_reg_info[0].start; + hw->mbx.addr_len = len; - len = pci_resource_len(pdev, 0) - region2_start; - if (len <= 0) - goto store_hw_info; + /* Map rstat space for resets */ + rstat_start = res_start + adapter->dev_ops.static_reg_info[1].start; + len = resource_size(&adapter->dev_ops.static_reg_info[1]); + hw->rstat.vaddr = devm_ioremap(dev, rstat_start, len); + if (!hw->rstat.vaddr) { + pci_err(pdev, "failed to allocate BAR0 rstat region\n"); - hw->hw_addr_region2 = ioremap(res_start + region2_start, len); - if (!hw->hw_addr_region2) { - dev_info(&pdev->dev, "ioremap(0x%04llx) region2 failed:\n", - res_start + region2_start); - return -EIO; + return -ENOMEM; } - hw->hw_addr_region2_len = len; -store_hw_info: + hw->rstat.addr_start = adapter->dev_ops.static_reg_info[1].start; + hw->rstat.addr_len = len; + + hw->back = adapter; hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; hw->subsystem_device_id = pdev->subsystem_device; - hw->back = adapter; return 0; } @@ -460,8 +468,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_request_mem_regions(pdev, pci_name(pdev)); if (err) { - dev_err(dev, - "pci_request_selected_regions failed %d\n", err); + pci_err(pdev, "pci_request_mem_regions failed %pe\n", ERR_PTR(err)); goto err_free; } @@ -642,7 +649,6 @@ int idpf_reset_recover(struct idpf_adapter *adapter) queue_delayed_work(adapter->serv_wq, &adapter->serv_task, msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07))); - queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); /* Initialize the state machine, also allocate memory and request * resources @@ -660,7 +666,6 @@ int idpf_reset_recover(struct idpf_adapter *adapter) return 0; init_err: - cancel_delayed_work_sync(&adapter->mbx_task); cancel_delayed_work_sync(&adapter->serv_task); idpf_deinit_dflt_mbx(adapter); @@ -675,7 +680,7 @@ int idpf_reset_recover(struct idpf_adapter *adapter) */ bool idpf_is_reset_detected(struct idpf_adapter *adapter) { - struct idpf_ctlq_reg reg; + struct idpf_ctlq_reg *reg; u32 arqlen; /* No need to check reset state in CORER */ if (test_bit(IDPF_CORER_IN_PROG, adapter->flags)) @@ -684,11 +689,11 @@ bool idpf_is_reset_detected(struct idpf_adapter *adapter) if (!adapter->hw.arq) return true; - reg = adapter->hw.arq->reg; - arqlen = readl(idpf_get_reg_addr(adapter, reg.len)); + reg = &adapter->hw.arq->reg; + arqlen = readl(idpf_get_mbx_reg_addr(adapter, reg->len)); /* We are in reset if either LEN or ENA bits are cleared. */ - return (!(arqlen & reg.len_mask) || !(arqlen & reg.len_ena_mask)); + return (!(arqlen & reg->len_mask) || !(arqlen & reg->len_ena_mask)); } /** @@ -697,16 +702,16 @@ bool idpf_is_reset_detected(struct idpf_adapter *adapter) */ static void idpf_reset_prepare(struct idpf_adapter *adapter) { + idpf_idc_issue_reset_event(adapter->cdev_info); + + idpf_detach_and_close(adapter); + idpf_vc_xn_shutdown(adapter->vcxn_mngr); idpf_vport_init_lock(adapter); cancel_delayed_work_sync(&adapter->serv_task); cancel_delayed_work_sync(&adapter->vc_event_task); set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); dev_info(idpf_adapter_to_dev(adapter), "Device FLR Reset initiated\n"); - idpf_device_detach(adapter); - idpf_netdev_stop_all(adapter); - idpf_idc_event(&adapter->rdma_data, IIDC_EVENT_WARN_RESET); - idpf_set_vport_state(adapter); idpf_vc_core_deinit(adapter); idpf_deinit_dflt_mbx(adapter); @@ -804,6 +809,11 @@ static void idpf_pci_err_resume(struct pci_dev *pdev) /* Wait for all init_task WQs to complete */ flush_delayed_work(&adapter->init_task); + + if (!err) { + idpf_attach_and_open(adapter); + idpf_idc_init(adapter); + } } #ifdef HAVE_PCI_ERROR_HANDLER_RESET_PREPARE diff --git a/idpf/src/idpf_mem.h b/idpf/src/idpf_mem.h index 3fb6ddf..3d0e43f 100644 --- a/idpf/src/idpf_mem.h +++ b/idpf/src/idpf_mem.h @@ -13,9 +13,14 @@ struct idpf_dma_mem { size_t size; }; -#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg))) -#define rd32(a, reg) readl((a)->hw_addr + (reg)) -#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg))) -#define rd64(a, reg) readq((a)->hw_addr + (reg)) +#define idpf_mbx_wr32(a, reg, value) writel((value), ((a)->mbx.vaddr + (reg))) +#define idpf_mbx_rd32(a, reg) readl((a)->mbx.vaddr + (reg)) +#define idpf_mbx_wr64(a, reg, value) writeq((value), ((a)->mbx.vaddr + (reg))) +#define idpf_mbx_rd64(a, reg) readq((a)->mbx.vaddr + (reg)) + +#define wr32(a, reg, value) idpf_mbx_wr32(a, reg, value) +#define rd32(a, reg) idpf_mbx_rd32(a, reg) +#define wr64(a, reg, value) idpf_mbx_wr64(a, reg, value) +#define rd64(a, reg) idpf_mbx_rd64(a, reg) #endif /* _IDPF_MEM_H_ */ diff --git a/idpf/src/idpf_txrx.c b/idpf/src/idpf_txrx.c index e0e5c4d..3e841bf 100644 --- a/idpf/src/idpf_txrx.c +++ b/idpf/src/idpf_txrx.c @@ -938,6 +938,8 @@ static int idpf_rx_map_buffer_rings(struct idpf_q_grp *q_grp) rxq->rx.bufq_bufs[j] = bufq->rx.bufs; + rxq->rx.refillqs = rx_qgrp->splitq.bufq_sets[j].refillqs; + if (!rxq->rx_hsplit_en) continue; @@ -1872,13 +1874,6 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, struct idpf_q_grp *q_g struct idpf_sw_queue *refillq = &bufq_set->refillqs[k]; -#ifdef CONFIG_IOMMU_BYPASS -#ifdef CONFIG_ARM64 - if (vport->adapter->iommu_byp.ddev) - refillq->dev = vport->adapter->iommu_byp.ddev; - else -#endif /* CONFIG_ARM64 */ -#endif /* CONFIG_IOMMU_BYPASS */ refillq->desc_count = q_grp->bufq_desc_count[j]; idpf_queue_set(GEN_CHK, refillq); @@ -3405,21 +3400,6 @@ void idpf_tx_set_tstamp_desc(union idpf_flex_tx_ctx_desc *ctx_desc, u32 idx) } #endif /* CONFIG_PTP_1588_CLOCK && CONFIG_PTP */ -/** - * idpf_tx_splitq_need_re - check whether RE bit needs to be set - * @tx_q: the tx ring to verify - * - * Return: true if RE bit needs to be set, false otherwise - */ -static inline bool idpf_tx_splitq_need_re(struct idpf_queue *tx_q) -{ - int gap = tx_q->next_to_use - tx_q->tx.last_re; - - gap += (gap < 0) ? tx_q->desc_count : 0; - - return gap >= IDPF_TX_SPLITQ_RE_MIN_GAP; -} - /** * idpf_tx_prepare_vlan_tag - prepare context descriptor with VLAN tag * @tx_q: TX queue to get the next available descriptor @@ -4432,6 +4412,16 @@ int idpf_xmit_xdpq(struct xdp_buff *xdp, struct idpf_queue *xdpq) return IDPF_XDP_CONSUMED; tx_params.compl_tag = buf_id; + + /* Set the RE bit to periodically "clean" the descriptor ring. + * MIN_GAP is set to MIN_RING size to ensure it will be set at + * least once each time around the ring. + */ + if (idpf_tx_splitq_need_re(xdpq)) { + tx_params.eop_cmd |= IDPF_TXD_FLEX_FLOW_CMD_RE; + xdpq->txq_grp->num_completions_pending++; + xdpq->tx.last_re = xdpq->next_to_use; + } } else { buf_id = ntu; } @@ -4444,8 +4434,6 @@ int idpf_xmit_xdpq(struct xdp_buff *xdp, struct idpf_queue *xdpq) #else tx_buf->raw = data; #endif - idpf_tx_buf_compl_tag(&xdpq->tx.bufs[buf_id]) = tx_params.compl_tag; - /* record length, and DMA address */ dma_unmap_len_set(tx_buf, len, size); dma_unmap_addr_set(tx_buf, dma, dma); @@ -5085,6 +5073,9 @@ static void idpf_vport_intr_rel_irq(struct idpf_vport *vport, #ifndef HAVE_NETDEV_IRQ_AFFINITY_AND_ARFS /* clear the affinity_mask in the IRQ descriptor */ irq_set_affinity_notifier(irq_num, NULL); +#ifndef HAVE_EXPORTED_IRQ_SET_AFFINITY + irq_set_affinity_hint(irq_num, NULL); +#endif /* !HAVE_EXPORTED_IRQ_SET_AFFINITY */ #endif /* !HAVE_NETDEV_IRQ_AFFINITY_AND_ARFS */ kfree(free_irq(irq_num, q_vector)); kfree(q_vector->name); diff --git a/idpf/src/idpf_txrx.h b/idpf/src/idpf_txrx.h index 06f901f..26d83e2 100644 --- a/idpf/src/idpf_txrx.h +++ b/idpf/src/idpf_txrx.h @@ -24,7 +24,6 @@ #include "virtchnl2_lan_desc.h" #define idpf_tx_buf_next(buf) (*(u32 *)&(buf)->priv) -#define idpf_tx_buf_compl_tag(buf) (*(u32 *)&(buf)->priv) LIBETH_SQE_CHECK_PRIV(u32); #define IDPF_LARGE_MAX_Q 256 @@ -79,7 +78,10 @@ LIBETH_SQE_CHECK_PRIV(u32); /* Default vector sharing */ #define IDPF_MBX_Q_VEC 1 #define IDPF_MIN_Q_VEC 1 -#define IDPF_MIN_RDMA_VEC 2 /* Minimum vectors to be shared with RDMA */ +#define IDPF_MIN_RDMA_VEC 2 +#ifdef CONFIG_RCA_SUPPORT +#define IDPF_MIN_RCA_VEC 1 +#endif /* CONFIG_RCA_SUPPORT */ #define IDPF_DFLT_TX_Q_DESC_COUNT 512 #define IDPF_DFLT_TX_COMPLQ_DESC_COUNT 512 @@ -1062,6 +1064,21 @@ static inline __le64 idpf_tx_singleq_build_ctob(u64 td_cmd, u64 td_offset, (td_tag << IDPF_TXD_QW1_L2TAG1_S)); } +/** + * idpf_tx_splitq_need_re - check whether RE bit needs to be set + * @tx_q: the tx ring to verify + * + * Return: true if RE bit needs to be set, false otherwise + */ +static inline bool idpf_tx_splitq_need_re(struct idpf_queue *tx_q) +{ + int gap = tx_q->next_to_use - tx_q->tx.last_re; + + gap += (gap < 0) ? tx_q->desc_count : 0; + + return gap >= IDPF_TX_SPLITQ_RE_MIN_GAP; +} + /** * idpf_tx_get_free_buf_id - get a free buffer ID from the refill queue * @refillq: refill queue to get buffer ID from diff --git a/idpf/src/idpf_vdcm_dev.c b/idpf/src/idpf_vdcm_dev.c index 779f2a0..b4fbb9c 100644 --- a/idpf/src/idpf_vdcm_dev.c +++ b/idpf/src/idpf_vdcm_dev.c @@ -334,7 +334,6 @@ static int idpf_vdcm_dev_set_vector_signal(struct idpf_vdcm *ivdm, int vector, if (ivdm->ctx[vector].trigger) { kfree(free_irq(irq, &ivdm->ctx[vector])); - kfree(ivdm->ctx[vector].name); eventfd_ctx_put(ivdm->ctx[vector].trigger); ivdm->ctx[vector].trigger = NULL; ivdm->ctx[vector].name = NULL; diff --git a/idpf/src/idpf_vf_dev.c b/idpf/src/idpf_vf_dev.c index 7cdb641..22a3b4a 100644 --- a/idpf/src/idpf_vf_dev.c +++ b/idpf/src/idpf_vf_dev.c @@ -5,47 +5,17 @@ #include "idpf_lan_vf_regs.h" #include "idpf_virtchnl.h" -/* LAN driver does not own all the BAR0 address space. This results in 2 BAR0 - * regions for VF device and the driver should map each region separately. - * - * Rest of BAR0 is owned by RDMA and it maps the pages on its own as it needs - * to map some of the pages for write combing (WC) instead of the default - * non-cached (NC) mapping that LAN driver does. In the VF BAR space, - * RDMA BAR0 memory lies between 64KB to 128KB. - * - * Also driver should map 1 page of RDMA from its space. - */ -#define IDPF_VF_BAR0_REGION1_END 0x11000 /* 64KB + 4KB */ -#define IDPF_VF_BAR0_REGION2_START 0x20000 /* 128KB */ - #define IDPF_VF_ITR_IDX_SPACING 0x40 -#define IDPF_VDEV_BAR0_REGION2_START (SIOV_REG_BAR_SIZE + 0x1000) - -static const struct idpf_ctlq_reg idpf_vdev_tx_regs = { - .head = VDEV_MBX_ATQH, - .tail = VDEV_MBX_ATQT, - .len = VDEV_MBX_ATQLEN, - .bah = VDEV_MBX_ATQBAH, - .bal = VDEV_MBX_ATQBAL -}; - -static const struct idpf_ctlq_reg idpf_vdev_rx_regs = { - .head = VDEV_MBX_ARQH, - .tail = VDEV_MBX_ARQT, - .len = VDEV_MBX_ARQLEN, - .bah = VDEV_MBX_ARQBAH, - .bal = VDEV_MBX_ARQBAL -}; - /** * idpf_vf_ctlq_reg_init - initialize default mailbox registers - * @hw: pointer to hw struct + * @adapter: adapter structure * @cq: pointer to the array of create control queues */ -static void idpf_vf_ctlq_reg_init(struct idpf_hw *hw, +static void idpf_vf_ctlq_reg_init(struct idpf_adapter *adapter, struct idpf_ctlq_create_info *cq) { + resource_size_t mbx_start = adapter->dev_ops.static_reg_info[0].start; int i; for (i = 0; i < IDPF_NUM_DFLT_MBX_Q; i++) { @@ -54,14 +24,18 @@ static void idpf_vf_ctlq_reg_init(struct idpf_hw *hw, switch (ccq->type) { case IDPF_CTLQ_TYPE_MAILBOX_TX: /* set head and tail registers in our local struct */ - if (hw->device_id == IDPF_DEV_ID_VF_SIOV) { - ccq->reg = idpf_vdev_tx_regs; + if (adapter->pdev->device == IDPF_DEV_ID_VF_SIOV) { + ccq->reg.head = VDEV_MBX_ATQH - mbx_start; + ccq->reg.tail = VDEV_MBX_ATQT - mbx_start; + ccq->reg.len = VDEV_MBX_ATQLEN - mbx_start; + ccq->reg.bah = VDEV_MBX_ATQBAH - mbx_start; + ccq->reg.bal = VDEV_MBX_ATQBAL - mbx_start; } else { - ccq->reg.head = VF_ATQH; - ccq->reg.tail = VF_ATQT; - ccq->reg.len = VF_ATQLEN; - ccq->reg.bah = VF_ATQBAH; - ccq->reg.bal = VF_ATQBAL; + ccq->reg.head = VF_ATQH - mbx_start; + ccq->reg.tail = VF_ATQT - mbx_start; + ccq->reg.len = VF_ATQLEN - mbx_start; + ccq->reg.bah = VF_ATQBAH - mbx_start; + ccq->reg.bal = VF_ATQBAL - mbx_start; } ccq->reg.len_mask = VF_ATQLEN_ATQLEN_M; ccq->reg.len_ena_mask = VF_ATQLEN_ATQENABLE_M; @@ -69,14 +43,18 @@ static void idpf_vf_ctlq_reg_init(struct idpf_hw *hw, break; case IDPF_CTLQ_TYPE_MAILBOX_RX: /* set head and tail registers in our local struct */ - if (hw->device_id == IDPF_DEV_ID_VF_SIOV) { - ccq->reg = idpf_vdev_rx_regs; + if (adapter->pdev->device == IDPF_DEV_ID_VF_SIOV) { + ccq->reg.head = VDEV_MBX_ARQH - mbx_start; + ccq->reg.tail = VDEV_MBX_ARQT - mbx_start; + ccq->reg.len = VDEV_MBX_ARQLEN - mbx_start; + ccq->reg.bah = VDEV_MBX_ARQBAH - mbx_start; + ccq->reg.bal = VDEV_MBX_ARQBAL - mbx_start; } else { - ccq->reg.head = VF_ARQH; - ccq->reg.tail = VF_ARQT; - ccq->reg.len = VF_ARQLEN; - ccq->reg.bah = VF_ARQBAH; - ccq->reg.bal = VF_ARQBAL; + ccq->reg.head = VF_ARQH - mbx_start; + ccq->reg.tail = VF_ARQT - mbx_start; + ccq->reg.len = VF_ARQLEN - mbx_start; + ccq->reg.bah = VF_ARQBAH - mbx_start; + ccq->reg.bal = VF_ARQBAL - mbx_start; } ccq->reg.len_mask = VF_ARQLEN_ARQLEN_M; ccq->reg.len_ena_mask = VF_ARQLEN_ARQENABLE_M; @@ -172,7 +150,7 @@ static int idpf_vf_intr_reg_init(struct idpf_vport *vport, */ static void idpf_vf_reset_reg_init(struct idpf_adapter *adapter) { - adapter->reset_reg.rstat = idpf_get_reg_addr(adapter, VFGEN_RSTAT); + adapter->reset_reg.rstat = idpf_get_rstat_reg_addr(adapter, VFGEN_RSTAT); adapter->reset_reg.rstat_m = VFGEN_RSTAT_VFR_STATE_M; } @@ -195,22 +173,14 @@ static void idpf_vf_trigger_reset(struct idpf_adapter *adapter, } /** - * idpf_vf_idc_register - register for idc callbacks - * @adapter: Driver specific private structure - */ -static int idpf_vf_idc_register(struct idpf_adapter *adapter) -{ - return idpf_idc_init_aux_device(&adapter->rdma_data, IIDC_FUNCTION_TYPE_VF); -} - -/** - * idpf_vf_idc_ops_init - Initialize IDC function pointers + * idpf_idc_vf_register - register for IDC callbacks * @adapter: Driver specific private structure + * + * Return: 0 on success or error code on failure. */ -static void idpf_vf_idc_ops_init(struct idpf_adapter *adapter) +static int idpf_idc_vf_register(struct idpf_adapter *adapter) { - adapter->dev_ops.idc_ops.idc_init = idpf_vf_idc_register; - adapter->dev_ops.idc_ops.idc_deinit = idpf_idc_deinit_aux_device; + return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_VF); } /** @@ -233,14 +203,18 @@ static void idpf_vf_reg_ops_init(struct idpf_adapter *adapter) void idpf_vf_dev_ops_init(struct idpf_adapter *adapter) { idpf_vf_reg_ops_init(adapter); - idpf_vf_idc_ops_init(adapter); + + adapter->dev_ops.idc_init = idpf_idc_vf_register; if (adapter->pdev->device == IDPF_DEV_ID_VF_SIOV) { - adapter->dev_ops.bar0_region1_size = SIOV_REG_BAR_SIZE; - adapter->dev_ops.bar0_region2_start = - IDPF_VDEV_BAR0_REGION2_START; + resource_set_range(&adapter->dev_ops.static_reg_info[0], + VDEV_MBX_START, IDPF_SIOV_MBX_REGION_SZ); + resource_set_range(&adapter->dev_ops.static_reg_info[1], + VFGEN_RSTAT, IDPF_SIOV_RSTAT_REGION_SZ); return; } - adapter->dev_ops.bar0_region1_size = IDPF_VF_BAR0_REGION1_END; - adapter->dev_ops.bar0_region2_start = IDPF_VF_BAR0_REGION2_START; + resource_set_range(&adapter->dev_ops.static_reg_info[0], + VF_BASE, IDPF_VF_MBX_REGION_SZ); + resource_set_range(&adapter->dev_ops.static_reg_info[1], + VFGEN_RSTAT, IDPF_VF_RSTAT_REGION_SZ); } diff --git a/idpf/src/idpf_virtchnl.c b/idpf/src/idpf_virtchnl.c index 9e0d009..561d964 100644 --- a/idpf/src/idpf_virtchnl.c +++ b/idpf/src/idpf_virtchnl.c @@ -4,6 +4,7 @@ #include "idpf.h" #include "idpf_virtchnl.h" #include "idpf_ptp.h" +#include /** * idpf_vid_to_vport - Translate vport id to vport pointer @@ -924,14 +925,18 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter) VIRTCHNL2_CAP_RSC_IPV6_TCP); caps.other_caps = - cpu_to_le64(VIRTCHNL2_CAP_RDMA | - VIRTCHNL2_CAP_SRIOV | + cpu_to_le64(VIRTCHNL2_CAP_SRIOV | + VIRTCHNL2_CAP_RDMA | + VIRTCHNL2_CAP_LAN_MEMORY_REGIONS | VIRTCHNL2_CAP_MACFILTER | VIRTCHNL2_CAP_SPLITQ_QSCHED | VIRTCHNL2_CAP_PROMISC | VIRTCHNL2_CAP_EDT | VIRTCHNL2_CAP_PTP | VIRTCHNL2_CAP_TX_CMPL_TSTMP | +#if defined(CONFIG_OEM_CAPS) || defined(CONFIG_P2P) + VIRTCHNL2_CAP_OEM | +#endif /* CONFIG_OEM_CAPS || CONFIG_P2P */ VIRTCHNL2_CAP_MISS_COMPL_TAG | VIRTCHNL2_CAP_LOOPBACK | VIRTCHNL2_CAP_VLAN); @@ -983,6 +988,180 @@ static int idpf_send_get_vlan_caps_msg(struct idpf_adapter *adapter) return 0; } +/** + * idpf_add_del_fsteer_filters - Send virtchnl add/del Flow Steering message + * @adapter: adapter info struct + * @rule: Flow steering rule to add/delete + * @opcode: VIRTCHNL2_OP_ADD_FLOW_RULE to add filter, or + * VIRTCHNL2_OP_DEL_FLOW_RULE to delete. All other values are invalid. + * + * Send ADD/DELETE flow steering virtchnl message and receive the result. + * + * Return: 0 on success, negative on failure. + */ +int idpf_add_del_fsteer_filters(struct idpf_adapter *adapter, + struct virtchnl2_flow_rule_add_del *rule, + enum virtchnl2_op opcode) +{ + int rule_count = le32_to_cpu(rule->count); + struct idpf_vc_xn_params xn_params = {}; + ssize_t reply_sz; + + if (opcode != VIRTCHNL2_OP_ADD_FLOW_RULE && + opcode != VIRTCHNL2_OP_DEL_FLOW_RULE) + return -EINVAL; + + xn_params.vc_op = opcode; + xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC; + xn_params.async = false; + xn_params.send_buf.iov_base = rule; + xn_params.send_buf.iov_len = struct_size(rule, rule_info, rule_count); + xn_params.recv_buf.iov_base = rule; + xn_params.recv_buf.iov_len = struct_size(rule, rule_info, rule_count); + + reply_sz = idpf_vc_xn_exec(adapter, &xn_params); + return reply_sz < 0 ? reply_sz : 0; +} + +/** + * idpf_send_get_lan_memory_regions - Send virtchnl get LAN memory regions msg + * @adapter: Driver specific private struct + * + * Return: 0 on success or error code on failure. + */ +static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter) +{ + struct virtchnl2_get_lan_memory_regions *rcvd_regions; + struct idpf_vc_xn_params xn_params = { }; + int num_regions, size; + struct idpf_hw *hw; + ssize_t reply_sz; + int err = 0; + + rcvd_regions = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL); + if (!rcvd_regions) + return -ENOMEM; + + xn_params.vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS; + xn_params.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN; + xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC; + + xn_params.recv_buf.iov_base = rcvd_regions; + reply_sz = idpf_vc_xn_exec(adapter, &xn_params); + if (reply_sz < 0) { + err = reply_sz; + goto get_lan_memory_regions_out; + } + + num_regions = le16_to_cpu(rcvd_regions->num_memory_regions); + size = struct_size(rcvd_regions, mem_reg, num_regions); + if (reply_sz < size) { + err = -EIO; + goto get_lan_memory_regions_out; + } + + if (size > IDPF_CTLQ_MAX_BUF_LEN) { + err = -EINVAL; + goto get_lan_memory_regions_out; + } + + hw = &adapter->hw; + hw->lan_regs = kcalloc(num_regions, sizeof(*hw->lan_regs), GFP_KERNEL); + if (!hw->lan_regs) { + err = -ENOMEM; + goto get_lan_memory_regions_out; + } + + for (int i = 0; i < num_regions; i++) { + hw->lan_regs[i].addr_len = + le64_to_cpu(rcvd_regions->mem_reg[i].size); + hw->lan_regs[i].addr_start = + le64_to_cpu(rcvd_regions->mem_reg[i].start_offset); + } + hw->num_lan_regs = num_regions; + +get_lan_memory_regions_out: + kfree(rcvd_regions); + + return err; +} + +/** + * idpf_calc_remaining_mmio_regs - calculate MMIO regions outside mbx and rstat + * @adapter: Driver specific private structure + * + * Called when idpf_send_get_lan_memory_regions is not supported. This will + * calculate the offsets and sizes for the regions before, in between, and + * after the mailbox and rstat MMIO mappings. + * + * Return: 0 on success or error code on failure. + */ +static int idpf_calc_remaining_mmio_regs(struct idpf_adapter *adapter) +{ + struct resource *first_static_reg = &adapter->dev_ops.static_reg_info[0]; + struct resource *second_static_reg = &adapter->dev_ops.static_reg_info[1]; + struct idpf_hw *hw = &adapter->hw; + + hw->num_lan_regs = IDPF_MMIO_MAP_FALLBACK_MAX_REMAINING; + hw->lan_regs = kcalloc(hw->num_lan_regs, sizeof(*hw->lan_regs), + GFP_KERNEL); + if (!hw->lan_regs) + return -ENOMEM; + + /* Swap regions in case rstat start is before mbx */ + if (second_static_reg->start < first_static_reg->start) { + first_static_reg = &adapter->dev_ops.static_reg_info[1]; + second_static_reg = &adapter->dev_ops.static_reg_info[0]; + } + + /* Region preceding mailbox */ + hw->lan_regs[0].addr_start = 0; + hw->lan_regs[0].addr_len = first_static_reg->start; + /* Region between mailbox and rstat */ + hw->lan_regs[1].addr_start = first_static_reg->end + 1; + hw->lan_regs[1].addr_len = second_static_reg->start - + hw->lan_regs[1].addr_start; + /* Region after rstat */ + hw->lan_regs[2].addr_start = second_static_reg->end + 1; + hw->lan_regs[2].addr_len = pci_resource_len(adapter->pdev, 0) - + hw->lan_regs[2].addr_start; + + return 0; +} + +/** + * idpf_map_lan_mmio_regs - map remaining LAN BAR regions + * @adapter: Driver specific private structure + * + * Return: 0 on success or error code on failure. + */ +static int idpf_map_lan_mmio_regs(struct idpf_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + struct idpf_hw *hw = &adapter->hw; + resource_size_t res_start; + + res_start = pci_resource_start(pdev, 0); + + for (int i = 0; i < hw->num_lan_regs; i++) { + resource_size_t start; + long len; + + len = hw->lan_regs[i].addr_len; + if (!len) + continue; + start = hw->lan_regs[i].addr_start + res_start; + + hw->lan_regs[i].vaddr = devm_ioremap(&pdev->dev, start, len); + if (!hw->lan_regs[i].vaddr) { + pci_err(pdev, "failed to allocate BAR0 region\n"); + return -ENOMEM; + } + } + + return 0; +} + /** * idpf_vport_alloc_max_qs - Allocate max queues for a vport * @adapter: Driver specific private structure @@ -2421,6 +2600,64 @@ int idpf_send_get_stats_msg(struct idpf_vport *vport) return 0; } +#ifdef CONFIG_UPLINK_PORT_STATS +/** + * idpf_send_get_port_stats_msg - Send get physical port representor stats msg + * @vport: vport to get stats for + * + * Returns 0 on success, negative on failure. + */ +int idpf_send_get_port_stats_msg(struct idpf_vport *vport) +{ + struct idpf_netdev_priv *np = netdev_priv(vport->netdev); + struct rtnl_link_stats64 *netstats = &np->netstats; + struct virtchnl2_port_stats stats_msg = { }; + struct idpf_vc_xn_params xn_params = { }; + struct virtchnl2_vport_stats *stats; + int reply_sz; + + stats_msg.vport_id = cpu_to_le32(vport->vport_id); + + xn_params.vc_op = VIRTCHNL2_OP_GET_PORT_STATS; + xn_params.send_buf.iov_base = (u8 *)&stats_msg; + xn_params.send_buf.iov_len = sizeof(stats_msg); + xn_params.recv_buf = xn_params.send_buf; + xn_params.timeout_ms = idpf_get_vc_xn_default_timeout(vport->adapter); + + reply_sz = idpf_vc_xn_exec(vport->adapter, &xn_params); + if (reply_sz < 0) + return reply_sz; + if (reply_sz < sizeof(stats_msg)) + return -EIO; + + spin_lock_bh(&np->stats_lock); + stats = &stats_msg.virt_port_stats; + netstats->rx_packets = le64_to_cpu(stats->rx_unicast) + + le64_to_cpu(stats->rx_multicast) + + le64_to_cpu(stats->rx_broadcast); + netstats->rx_bytes = le64_to_cpu(stats->rx_bytes); + netstats->rx_dropped = le64_to_cpu(stats->rx_discards); + netstats->rx_over_errors = le64_to_cpu(stats->rx_overflow_drop); + netstats->rx_length_errors = le64_to_cpu(stats->rx_invalid_frame_length); + + netstats->tx_packets = le64_to_cpu(stats->tx_unicast) + + le64_to_cpu(stats->tx_multicast) + + le64_to_cpu(stats->tx_broadcast); + netstats->tx_bytes = le64_to_cpu(stats->tx_bytes); + netstats->tx_errors = le64_to_cpu(stats->tx_errors); + netstats->tx_dropped = le64_to_cpu(stats->tx_discards); + + vport->port_stats.vport_stats = stats_msg.virt_port_stats; + + memcpy(vport->port_stats.phy_port_stats, &stats_msg.phy_port_stats, + sizeof(*vport->port_stats.phy_port_stats)); + + spin_unlock_bh(&np->stats_lock); + + return 0; +} + +#endif /* CONFIG_UPLINK_PORT_STATS */ /** * idpf_send_get_set_rss_hash_msg - Send set or get rss hash message * @vport: virtual port data structure @@ -3015,7 +3252,7 @@ int idpf_init_dflt_mbx(struct idpf_adapter *adapter) struct idpf_hw *hw = &adapter->hw; int err; - adapter->dev_ops.reg_ops.ctlq_reg_init(hw, ctlq_info); + adapter->dev_ops.reg_ops.ctlq_reg_init(adapter, ctlq_info); err = idpf_ctlq_init(hw, IDPF_NUM_DFLT_MBX_Q, ctlq_info); if (err) @@ -3033,6 +3270,7 @@ int idpf_init_dflt_mbx(struct idpf_adapter *adapter) } adapter->state = __IDPF_VER_CHECK; + queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); return 0; } @@ -3043,6 +3281,8 @@ int idpf_init_dflt_mbx(struct idpf_adapter *adapter) */ void idpf_deinit_dflt_mbx(struct idpf_adapter *adapter) { + idpf_mb_intr_rel_irq(adapter); + cancel_delayed_work_sync(&adapter->mbx_task); if (adapter->hw.arq && adapter->hw.asq) { idpf_mb_clean(adapter); idpf_ctlq_deinit(&adapter->hw); @@ -3100,6 +3340,35 @@ static int idpf_vport_params_buf_alloc(struct idpf_adapter *adapter) return -ENOMEM; } +#if defined(CONFIG_OEM_CAPS) || defined(CONFIG_P2P) +/** + * idpf_get_oem_caps - Send virtchnl get oem capabilities message + * @adapter: Driver specific private structure + * + * Send virtchnl get oem capabilities message. + * Returns 0 on success, negative on failure. + */ +static int idpf_get_oem_caps(struct idpf_adapter *adapter) +{ + struct virtchnl2_oem_caps oem_caps_msg = {}; + struct idpf_vc_xn_params xn_params = {}; + ssize_t reply_sz; + + xn_params.vc_op = VIRTCHNL2_OP_GET_OEM_CAPS; + xn_params.timeout_ms = idpf_get_vc_xn_default_timeout(adapter); + xn_params.send_buf.iov_base = &oem_caps_msg; + xn_params.send_buf.iov_len = sizeof(oem_caps_msg); + xn_params.recv_buf.iov_base = &adapter->oem_caps; + xn_params.recv_buf.iov_len = sizeof(struct virtchnl2_oem_caps); + + reply_sz = idpf_vc_xn_exec(adapter, &xn_params); + if (reply_sz < 0) + return reply_sz; + + return 0; +} + +#endif /* CONFIG_OEM_CAPS || CONFIG_P2P */ /** * idpf_vc_core_init - Initialize state machine and get driver specific * resources @@ -3160,6 +3429,36 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) msleep(task_delay); } + if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_LAN_MEMORY_REGIONS)) { + if (adapter->pdev->device == IDPF_DEV_ID_VF_SIOV) + err = idpf_calc_remaining_mmio_regs(adapter); + else + err = idpf_send_get_lan_memory_regions(adapter); + if (err) { + dev_err(&adapter->pdev->dev, "Failed to get LAN memory regions: %d\n", + err); + return -EINVAL; + } + } else { + /* Fallback to mapping the remaining regions of the entire BAR */ + err = idpf_calc_remaining_mmio_regs(adapter); + if (err) { + dev_err(&adapter->pdev->dev, "Failed to allocate BAR0 region(s): %d\n", + err); + return -ENOMEM; + } + } + + err = idpf_map_lan_mmio_regs(adapter); + if (err) { + dev_err(&adapter->pdev->dev, "Failed to map BAR0 region(s): %d\n", + err); + return -ENOMEM; + } + + if (adapter->dev_ops.reg_ops.oicr_reset_reg_init) + adapter->dev_ops.reg_ops.oicr_reset_reg_init(adapter); + pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter)); num_max_vports = idpf_get_max_vports(adapter); adapter->max_vports = num_max_vports; @@ -3187,6 +3486,14 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) idpf_send_get_edt_caps(adapter); +#if defined(CONFIG_OEM_CAPS) || defined(CONFIG_P2P) + if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_OEM)) { + err = idpf_get_oem_caps(adapter); + if (err) + dev_err(idpf_adapter_to_dev(adapter), "Failed to receive OEM capabilities\n"); + } + +#endif /* CONFIG_OEM_CAPS || CONFIG_P2P */ err = idpf_intr_req(adapter); if (err) { dev_err(idpf_adapter_to_dev(adapter), "failed to enable interrupt vectors: %d\n", @@ -3265,6 +3572,79 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) return -EAGAIN; } +/** + * idpf_vport_is_cap_ena - Check if vport capability is enabled + * @vport: Private data struct + * @flag: flag(s) to check + * + * Return: true if the capability is supported, false otherwise + */ +bool idpf_vport_is_cap_ena(struct idpf_vport *vport, u16 flag) +{ + struct virtchnl2_create_vport *vport_msg; + + vport_msg = vport->adapter->vport_params_recvd[vport->idx]; + + return !!(le16_to_cpu(vport_msg->vport_flags) & flag); +} + +/** + * idpf_sideband_flow_type_ena - Check if steering is enabled for flow type + * @vport: Private data struct + * @flow_type: flow type to check (from ethtool.h) + * + * Return: true if sideband filters are allowed for @flow_type, false otherwise + */ +bool idpf_sideband_flow_type_ena(struct idpf_vport *vport, u32 flow_type) +{ + struct virtchnl2_create_vport *vport_msg; + __le64 caps; + + vport_msg = vport->adapter->vport_params_recvd[vport->idx]; + caps = vport_msg->sideband_flow_caps; + + switch (flow_type) { + case TCP_V4_FLOW: + return !!(caps & cpu_to_le64(VIRTCHNL2_FLOW_IPV4_TCP)); + case UDP_V4_FLOW: + return !!(caps & cpu_to_le64(VIRTCHNL2_FLOW_IPV4_UDP)); + default: + return false; + } +} + +/** + * idpf_sideband_action_ena - Check if steering is enabled for action + * @vport: Private data struct + * @fsp: flow spec + * + * Return: true if sideband filters are allowed for @fsp, false otherwise + */ +bool idpf_sideband_action_ena(struct idpf_vport *vport, + struct ethtool_rx_flow_spec *fsp) +{ + struct virtchnl2_create_vport *vport_msg; + unsigned int supp_actions; + + vport_msg = vport->adapter->vport_params_recvd[vport->idx]; + supp_actions = le32_to_cpu(vport_msg->sideband_flow_actions); + + /* Actions Drop/Wake are not supported */ + if (fsp->ring_cookie == RX_CLS_FLOW_DISC || + fsp->ring_cookie == RX_CLS_FLOW_WAKE) + return false; + + return !!(supp_actions & VIRTCHNL2_ACTION_QUEUE); +} + +unsigned int idpf_fsteer_max_rules(struct idpf_vport *vport) +{ + struct virtchnl2_create_vport *vport_msg; + + vport_msg = vport->adapter->vport_params_recvd[vport->idx]; + return le32_to_cpu(vport_msg->flow_steer_max_rules); +} + /** * idpf_vc_core_deinit - Device deinit routine * @adapter: Driver specific private structure @@ -3283,12 +3663,12 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter) idpf_vc_xn_shutdown(adapter->vcxn_mngr); idpf_ptp_release(adapter); idpf_deinit_task(adapter); + idpf_idc_deinit_core_aux_device(adapter->cdev_info); idpf_intr_rel(adapter); if (remove_in_prog) idpf_vc_xn_shutdown(adapter->vcxn_mngr); cancel_delayed_work_sync(&adapter->serv_task); - cancel_delayed_work_sync(&adapter->mbx_task); idpf_vport_params_buf_rel(adapter); @@ -3395,6 +3775,24 @@ static void idpf_vport_edt_init(struct idpf_vport *vport) vport->tw_horizon = le64_to_cpu(adapter->edt_caps.time_horizon_ns); } +#ifdef CONFIG_UPLINK_PORT_STATS +/** + * idpf_uplink_port_stats_alloc - Allocate memory for uplink port representor + * statistics + * @vport: Virtual port + */ +static int idpf_uplink_port_stats_alloc(struct idpf_vport *vport) +{ + vport->port_stats.phy_port_stats = kzalloc(sizeof(*vport->port_stats.phy_port_stats), + GFP_ATOMIC); + if (!vport->port_stats.phy_port_stats) + return -ENOMEM; + + return 0; +} + +#endif /* CONFIG_UPLINK_PORT_STATS */ + #ifdef HAVE_XDP_SUPPORT /** * idpf_vport_set_xdp_tx_desc_handler - Set a handler function for XDP Tx @@ -3444,6 +3842,11 @@ int idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q) if (le16_to_cpu(vport_msg->vport_flags) & VIRTCHNL2_VPORT_UPLINK_PORT) { set_bit(IDPF_VPORT_UPLINK_PORT, vport_config->flags); +#ifdef CONFIG_UPLINK_PORT_STATS + err = idpf_uplink_port_stats_alloc(vport); + if (err) + return err; +#endif /* CONFIG_UPLINK_PORT_STATS */ } vport_config->max_q.max_txq = max_q->max_txq; @@ -3497,8 +3900,6 @@ int idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q) vport->crc_enable = adapter->crc_enable; idpf_vport_edt_init(vport); - INIT_WORK(&vport->finish_reset_task, idpf_finish_soft_reset); - if (!(vport_msg->vport_flags & cpu_to_le16(VIRTCHNL2_VPORT_UPLINK_PORT))) return 0; @@ -4172,3 +4573,42 @@ int idpf_set_vlan_features(struct idpf_vport *vport, netdev_features_t features) return 0; } + +/** + * idpf_idc_rdma_vc_send_sync - virtchnl send callback for IDC registered drivers + * @cdev_info: IDC core device info pointer + * @send_msg: message to send + * @msg_size: size of message to send + * @recv_msg: message to populate on reception of response + * @recv_len: length of message copied into recv_msg or 0 on error + * + * Return: 0 on success or error code on failure. + */ +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info, + u8 *send_msg, u16 msg_size, + u8 *recv_msg, u16 *recv_len) +{ + struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev); + struct idpf_vc_xn_params xn_params = { }; + ssize_t reply_sz; + u16 recv_size; + + if (!recv_msg || !recv_len || msg_size > IDPF_CTLQ_MAX_BUF_LEN) + return -EINVAL; + + recv_size = min_t(u16, *recv_len, IDPF_CTLQ_MAX_BUF_LEN); + *recv_len = 0; + xn_params.vc_op = VIRTCHNL2_OP_RDMA; + xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC; + xn_params.send_buf.iov_base = send_msg; + xn_params.send_buf.iov_len = msg_size; + xn_params.recv_buf.iov_base = recv_msg; + xn_params.recv_buf.iov_len = recv_size; + reply_sz = idpf_vc_xn_exec(adapter, &xn_params); + if (reply_sz < 0) + return reply_sz; + *recv_len = reply_sz; + + return 0; +} +EXPORT_SYMBOL_GPL(idpf_idc_rdma_vc_send_sync); diff --git a/idpf/src/idpf_virtchnl.h b/idpf/src/idpf_virtchnl.h index 255d478..433045f 100644 --- a/idpf/src/idpf_virtchnl.h +++ b/idpf/src/idpf_virtchnl.h @@ -128,6 +128,11 @@ int idpf_queue_reg_init(struct idpf_vport *vport, struct idpf_q_grp *q_grp, struct virtchnl2_queue_reg_chunks *chunks); int idpf_vport_queue_ids_init(struct idpf_q_grp *q_grp, struct virtchnl2_queue_reg_chunks *chunks); +bool idpf_vport_is_cap_ena(struct idpf_vport *vport, u16 flag); +bool idpf_sideband_flow_type_ena(struct idpf_vport *vport, u32 flow_type); +bool idpf_sideband_action_ena(struct idpf_vport *vport, + struct ethtool_rx_flow_spec *fsp); +unsigned int idpf_fsteer_max_rules(struct idpf_vport *vport); int idpf_recv_mb_msg(struct idpf_adapter *adapter); int idpf_send_mb_msg(struct idpf_adapter *adapter, u32 op, u16 msg_size, u8 *msg, u16 cookie); @@ -168,6 +173,9 @@ int idpf_send_map_unmap_queue_vector_msg(struct idpf_vport *vport, int idpf_add_del_mac_filters(struct idpf_vport *vport, struct idpf_netdev_priv *np, bool add, bool async); +int idpf_add_del_fsteer_filters(struct idpf_adapter *adapter, + struct virtchnl2_flow_rule_add_del *rule, + enum virtchnl2_op opcode); int idpf_set_promiscuous(struct idpf_adapter *adapter, struct idpf_vport_user_config_data *config_data, u32 vport_id); @@ -183,8 +191,14 @@ int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, struct idpf_rss_data *rss_data, bool get); void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr); +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info, + u8 *send_msg, u16 msg_size, + u8 *recv_msg, u16 *recv_len); int idpf_send_get_set_rss_hash_msg(struct idpf_vport *vport, bool get); int idpf_set_vlan_features(struct idpf_vport *vport, netdev_features_t features); +#ifdef CONFIG_UPLINK_PORT_STATS +int idpf_send_get_port_stats_msg(struct idpf_vport *vport); +#endif /* CONFIG_UPLINK_PORT_STATS */ int idpf_send_create_adi_msg(struct idpf_adapter *adapter, struct virtchnl2_non_flex_create_adi *vchnl_adi); int idpf_send_destroy_adi_msg(struct idpf_adapter *adapter, diff --git a/idpf/src/idpf_virtchnl_ptp.c b/idpf/src/idpf_virtchnl_ptp.c index 7ae9fc7..27f69cd 100644 --- a/idpf/src/idpf_virtchnl_ptp.c +++ b/idpf/src/idpf_virtchnl_ptp.c @@ -40,8 +40,8 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter) struct idpf_ptp_secondary_mbx *scnd_mbx; struct idpf_ptp *ptp = adapter->ptp; enum idpf_ptp_access access_type; + int reply_sz, ret = 0; u32 temp_offset; - int reply_sz; xn_params.timeout_ms = idpf_get_vc_xn_default_timeout(adapter); recv_ptp_caps_msg = kzalloc(sizeof(struct virtchnl2_ptp_get_caps), @@ -54,9 +54,12 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter) reply_sz = idpf_vc_xn_exec(adapter, &xn_params); if (reply_sz < 0) - return reply_sz; + ret = reply_sz; else if (reply_sz != sizeof(*recv_ptp_caps_msg)) - return -EIO; + ret = -EIO; + + if (ret) + goto get_caps_out; ptp->caps = le32_to_cpu(recv_ptp_caps_msg->caps); ptp->base_incval = le64_to_cpu(recv_ptp_caps_msg->base_incval); @@ -115,7 +118,7 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter) discipline_clock: access_type = ptp->adj_dev_clk_time_access; if (access_type != IDPF_PTP_DIRECT) - return 0; + goto get_caps_out; clk_adj_offsets = recv_ptp_caps_msg->clk_adj_offsets; @@ -145,9 +148,10 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter) temp_offset = le32_to_cpu(clk_adj_offsets.phy_clk_shadj_h); ptp->dev_clk_regs.phy_shadj_h = idpf_get_reg_addr(adapter, temp_offset); +get_caps_out: kfree(recv_ptp_caps_msg); - return 0; + return ret; } /** diff --git a/idpf/src/idpf_xsk.c b/idpf/src/idpf_xsk.c index c4ca0cd..304c296 100644 --- a/idpf/src/idpf_xsk.c +++ b/idpf/src/idpf_xsk.c @@ -255,14 +255,25 @@ idpf_xmit_splitq_zc(struct idpf_queue *xdpq, int budget) tx_parms.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; tx_parms.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; + /* Set the RE bit to periodically "clean" the descriptor ring. + * MIN_GAP is set to MIN_RING size to ensure it will be set at + * least once each time around the ring. + */ + if (idpf_tx_splitq_need_re(xdpq)) { + tx_parms.eop_cmd |= IDPF_TXD_FLEX_FLOW_CMD_RE; + xdpq->txq_grp->num_completions_pending++; + xdpq->tx.last_re = xdpq->next_to_use; + } + idpf_tx_splitq_build_desc(tx_desc, &tx_parms, tx_parms.eop_cmd | tx_parms.offload.td_cmd, desc.len); + tx_buf->rs_idx = ntu; + ntu++; if (ntu == xdpq->desc_count) ntu = 0; - idpf_tx_buf_compl_tag(tx_buf) = tx_parms.compl_tag; } if (likely(tx_desc)) { @@ -369,6 +380,7 @@ idpf_tx_clean_zc(struct idpf_queue *xdpq, u16 ntc, u16 clean_count, struct libeth_sq_napi_stats *cleaned, u16 buf_id) { + bool fs = idpf_queue_has(FLOW_SCH_EN, xdpq); struct idpf_tx_buf *tx_buf; u32 xsk_frames = 0; u16 i; @@ -381,7 +393,7 @@ idpf_tx_clean_zc(struct idpf_queue *xdpq, u16 ntc, u16 clean_count, goto skip; } - if (unlikely(idpf_queue_has(FLOW_SCH_EN, xdpq))) { + if (fs) { clean_count = 1; tx_buf = &xdpq->tx.bufs[buf_id]; } else { @@ -406,6 +418,9 @@ idpf_tx_clean_zc(struct idpf_queue *xdpq, u16 ntc, u16 clean_count, xsk_frames++; } + if (fs) + idpf_post_buf_refill(xdpq->tx.refillq, buf_id); + ++ntc; if (unlikely(ntc >= xdpq->desc_count)) ntc = 0; diff --git a/idpf/src/iidc.h b/idpf/src/iidc.h index b63067a..4a6b48a 100644 --- a/idpf/src/iidc.h +++ b/idpf/src/iidc.h @@ -24,8 +24,8 @@ * the version check fails, the auxiliary driver should fail the probe and log * an appropriate message. */ -#define IIDC_MAJOR_VER 10 -#define IIDC_MINOR_VER 3 +#define IIDC_MAJOR_VER 11 +#define IIDC_MINOR_VER 0 enum iidc_event_type { IIDC_EVENT_BEFORE_MTU_CHANGE, @@ -223,6 +223,14 @@ enum iidc_function_type { struct iidc_core_dev_info { struct pci_dev *pdev; /* PCI device of corresponding to main function */ struct auxiliary_device *adev; + /* Current active RDMA protocol */ + enum iidc_rdma_protocol rdma_protocol; + /* Opaque pointer for core driver specific data tracking. This memory + * will be alloc'd and freed by the core driver and used for + * private data accessible only to the specific auxiliary driver. + */ + void *iidc_priv; + /* KVA / Linear address corresponding to BAR0 of underlying * pci_device. */ @@ -241,8 +249,6 @@ struct iidc_core_dev_info { enum iidc_function_type ftype; u16 vport_id; - /* Current active RDMA protocol */ - enum iidc_rdma_protocol rdma_protocol; struct iidc_qos_params qos_info; struct net_device *netdev; diff --git a/idpf/src/iidc_rdma_idpf.h b/idpf/src/iidc_rdma_idpf.h new file mode 100644 index 0000000..084fbfc --- /dev/null +++ b/idpf/src/iidc_rdma_idpf.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2019-2025 Intel Corporation */ + +#ifndef _IIDC_RDMA_IDPF_H_ +#define _IIDC_RDMA_IDPF_H_ + +#include "iidc.h" + +/* struct to be populated by core LAN PCI driver */ +struct iidc_rdma_vport_dev_info { + struct auxiliary_device *adev; + struct auxiliary_device *core_adev; + struct net_device *netdev; + u16 vport_id; +}; + +struct iidc_rdma_vport_auxiliary_dev { + struct auxiliary_device adev; + struct iidc_rdma_vport_dev_info *vdev_info; +}; + +struct iidc_rdma_vport_auxiliary_drv { + struct auxiliary_driver adrv; + void (*event_handler)(struct iidc_rdma_vport_dev_info *vdev, + struct iidc_event *event); +}; + +struct iidc_rdma_lan_mapped_mem_region { + u8 __iomem *region_addr; + __le64 size; + __le64 start_offset; +}; + +struct iidc_rdma_priv_dev_info { + struct msix_entry *msix_entries; + u16 msix_count; /* How many vectors are reserved for this device */ + enum iidc_function_type ftype; + __le16 num_memory_regions; + struct iidc_rdma_lan_mapped_mem_region *mapped_mem_regions; +}; + +int idpf_idc_vport_dev_ctrl(struct iidc_core_dev_info *cdev_info, bool up); +int idpf_idc_request_reset(struct iidc_core_dev_info *cdev_info, + enum iidc_reset_type __always_unused reset_type); +int idpf_idc_rdma_vc_send_sync(struct iidc_core_dev_info *cdev_info, + u8 *send_msg, u16 msg_size, + u8 *recv_msg, u16 *recv_len); +#endif /* _IIDC_RDMA_IDPF_H_ */ diff --git a/idpf/src/kcompat-generator.sh b/idpf/src/kcompat-generator.sh index 068c7ec..556aba8 100644 --- a/idpf/src/kcompat-generator.sh +++ b/idpf/src/kcompat-generator.sh @@ -83,7 +83,11 @@ function gen-cleanup() { rcuh='include/linux/rcupdate.h' gen NEED_DEFINE_FREE if macro DEFINE_FREE absent in "$ch" gen NEED___DEFINE_CLASS_IS_CONDITIONAL if macro __DEFINE_CLASS_IS_CONDITIONAL absent in "$ch" - gen NEED_DEFINE_GUARD_MUTEX if invocation of macro DEFINE_GUARD absent or lacks mutex_lock in "$mh" + # Check for mutex guards in both old and new APIs + HAVE_MUTEX_GUARDS=0 + check invocation of macro DEFINE_LOCK_GUARD_1 matches mutex in "$mh" && HAVE_MUTEX_GUARDS=1 + check invocation of macro DEFINE_GUARD matches mutex in "$mh" && HAVE_MUTEX_GUARDS=1 + gen NEED_DEFINE_GUARD_MUTEX if string "$HAVE_MUTEX_GUARDS" equals 0 gen NEED_LOCK_GUARD_FOR_RCU if invocation of macro DEFINE_LOCK_GUARD_0 absent or lacks rcu in "$rcuh" gen NEED_DEFINE_FREE_KFREE if invocation of macro DEFINE_FREE absent or lacks kfree in "$slabh" gen NEED_DEFINE_FREE_KVFREE if invocation of macro DEFINE_FREE absent or lacks kvfree in "$slabh" @@ -183,6 +187,7 @@ function gen-dpll() { gen HAVE_DPLL_PHASE_OFFSET if method phase_offset_get of dpll_pin_ops in "$dh" gen HAVE_DPLL_PHASE_OFFSET_MONITOR if method phase_offset_monitor_set of dpll_device_ops in "$dh" gen NEED_DPLL_NETDEV_PIN_SET if fun dpll_netdev_pin_set absent in "$dh" + gen NEED_DPLL_TRACKER if typedef dpll_tracker absent in "$dh" } function gen-ethtool() { @@ -379,7 +384,10 @@ function gen-packing() { } function gen-pci() { + ioporth='include/linux/ioport.h' pcih='include/linux/pci.h' + gen HAVE_RESOURCE_SET_RANGE if fun resource_set_range in "$ioporth" + gen HAVE_RESOURCE_SET_SIZE if fun resource_set_size in "$ioporth" gen HAVE_PCI_MSIX_ALLOC_IRQ_AT if fun pci_msix_alloc_irq_at in "$pcih" gen HAVE_PCI_MSIX_CAN_ALLOC_DYN if fun pci_msix_can_alloc_dyn in "$pcih" gen HAVE_PCI_MSIX_FREE_IRQ if fun pci_msix_free_irq in "$pcih" @@ -404,6 +412,7 @@ function gen-ptp() { gen HAVE_PTP_CANCEL_WORKER_SYNC if fun ptp_cancel_worker_sync in "$clockh" gen HAVE_PTP_CLOCK_DO_AUX_WORK if method do_aux_work of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_ADJFINE if method adjfine of ptp_clock_info in "$clockh" + gen HAVE_PTP_CLOCK_INFO_GETCYCLES64 if method getcycles64 of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_GETTIME64 if method gettime64 of ptp_clock_info in "$clockh" gen HAVE_PTP_CLOCK_INFO_GETTIMEX64 if method gettimex64 of ptp_clock_info in "$clockh" gen HAVE_PTP_FIND_PIN_UNLOCKED if fun ptp_find_pin_unlocked in "$clockh" @@ -525,8 +534,9 @@ function gen-other() { gen HAVE_MDEV_GET_DRVDATA if fun mdev_get_drvdata in include/linux/mdev.h gen HAVE_MDEV_REGISTER_PARENT if fun mdev_register_parent in include/linux/mdev.h gen HAVE_VM_FLAGS_API if fun vm_flags_init in include/linux/mm.h + gen NEED_MODULE_INFO_WITHOUT_CHECK if implementation of macro MODULE_INFO matches __builtin_strlen in include/linux/moduleparam.h gen HAVE_NL_SET_ERR_MSG_FMT if macro NL_SET_ERR_MSG_FMT in include/linux/netlink.h - gen NEED_DEFINE_SIMPLE_DEV_OPS if macro DEFINE_SIMPLE_DEV_OPS absent in include/linux/pm.h + gen NEED_DEFINE_SIMPLE_DEV_PM_OPS if macro DEFINE_SIMPLE_DEV_PM_OPS absent in include/linux/pm.h gen NEED_PM_SLEEP_PTR if macro pm_sleep_ptr absent in include/linux/pm.h gen NEED_DEV_PM_DOMAIN_ATTACH if fun dev_pm_domain_attach absent in include/linux/pm_domain.h include/linux/pm.h gen NEED_DEV_PM_DOMAIN_DETACH if fun dev_pm_domain_detach absent in include/linux/pm_domain.h include/linux/pm.h diff --git a/idpf/src/kcompat.c b/idpf/src/kcompat.c index 3c4e524..fb20942 100644 --- a/idpf/src/kcompat.c +++ b/idpf/src/kcompat.c @@ -2697,3 +2697,37 @@ void pci_disable_ptm(struct pci_dev *dev) #endif /* HAVE_STRUCT_PCI_DEV_PTM_ENABLED && CONFIG_PCIE_PTM */ } #endif /* NEED_PCI_DISABLE_PTM */ + +#ifndef HAVE_RESOURCE_SET_SIZE +/** + * resource_set_size - Calculate resource end address from size and start + * @res: Resource descriptor + * @size: Size of the resource + * + * Calculate the end address for @res based on @size. + * + * Note: The start address of @res must be set when calling this function. + * Prefer resource_set_range() if setting both the start address and @size. + */ +void resource_set_size(struct resource *res, resource_size_t size) +{ + res->end = res->start + size - 1; +} +#endif /* !HAVE_RESOURCE_SET_SIZE */ + +#ifndef HAVE_RESOURCE_SET_RANGE +/** + * resource_set_range - Set resource start and end addresses + * @res: Resource descriptor + * @start: Start address for the resource + * @size: Size of the resource + * + * Set @res start address and calculate the end address based on @size. + */ +void resource_set_range(struct resource *res, resource_size_t start, + resource_size_t size) +{ + res->start = start; + resource_set_size(res, size); +} +#endif /* !HAVE_RESOURCE_SET_RANGE */ diff --git a/idpf/src/kcompat.h b/idpf/src/kcompat.h index 6a2d15d..0c1d918 100644 --- a/idpf/src/kcompat.h +++ b/idpf/src/kcompat.h @@ -58,7 +58,7 @@ /* any of the features that need to alter module_init */ #if !defined(HAVE_XARRAY_API) -static int __init kc_module_init_impl(void) +static inline int __init kc_module_init_impl(void) { #ifdef HAVE_XARRAY_API #else diff --git a/idpf/src/kcompat_impl.h b/idpf/src/kcompat_impl.h index 2d2132e..273c327 100644 --- a/idpf/src/kcompat_impl.h +++ b/idpf/src/kcompat_impl.h @@ -3414,6 +3414,18 @@ enum dpll_lock_status_error { #define dpll_netdev_pin_clear netdev_dpll_pin_clear #endif /* NEED_DPLL_NETDEV_PIN_SET */ +#ifdef NEED_DPLL_TRACKER +#ifdef CONFIG_DPLL +#include +#define dpll_device_get(clock_id, device_idx, module, tracker) \ + dpll_device_get(clock_id, device_idx, module) +#define dpll_device_put(dpll, tracker) dpll_device_put(dpll) +#define dpll_pin_get(clock_id, pin_idx, module, prop, tracker) \ + dpll_pin_get(clock_id, pin_idx, module, prop) +#define dpll_pin_put(pin, tracker) dpll_pin_put(pin) +#endif /* CONFIG_DPLL */ +#endif /* NEED_DPLL_TRACKER */ + #ifdef NEED_RADIX_TREE_EMPTY static inline bool radix_tree_empty(struct radix_tree_root *root) { @@ -3626,12 +3638,36 @@ void _kc_eventfd_signal(struct eventfd_ctx *ctx) #define TCP_MIN_MSS 88U #endif -#ifdef NEED_DEFINE_SIMPLE_DEV_OPS -#define DEFINE_SIMPLE_DEV_OPS(name, suspend_fn, resume_fn) \ +#ifdef NEED_DEFINE_SIMPLE_DEV_PM_OPS +#define DEFINE_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) -#endif /* NEED_DEFINE_SIMPLE_DEV_OPS */ +#endif /* NEED_DEFINE_SIMPLE_DEV_PM_OPS */ #ifdef NEED_PM_SLEEP_PTR #define pm_sleep_ptr(_ptr) (_ptr) #endif /* NEED_PM_SLEEP_PTR */ + +#ifdef NEED_MODULE_INFO_WITHOUT_CHECK +/* upstream commit ae83f3b72621 ("module: Add compile-time check for embedded + * NUL characters") added an assert preventing embedding dishonest licenses, + * like "GPL\0, but proprietary for XXX part". Unfortunately __builtin_strlen() + * used does not work in some of our CI builds, so just remove that (essentially + * "reverting" the upstream commit). + */ +#include +#undef MODULE_INFO +#define MODULE_INFO(tag, info) \ + static const char __UNIQUE_ID(modinfo)[] \ + __used __section(".modinfo") __aligned(1) \ + = __MODULE_INFO_PREFIX __stringify(tag) "=" info +#endif /* NEED_MODULE_INFO_WITHOUT_CHECK */ + +#ifndef HAVE_RESOURCE_SET_SIZE +void resource_set_size(struct resource *res, resource_size_t size); +#endif /* !HAVE_RESOURCE_SET_SIZE */ +#ifndef HAVE_RESOURCE_SET_RANGE +void resource_set_range(struct resource *res, resource_size_t start, + resource_size_t size); +#endif /* !HAVE_RESOURCE_SET_RANGE */ + #endif /* _KCOMPAT_IMPL_H_ */ diff --git a/idpf/src/virtchnl2.h b/idpf/src/virtchnl2.h index 4df7f5f..a085301 100644 --- a/idpf/src/virtchnl2.h +++ b/idpf/src/virtchnl2.h @@ -441,6 +441,7 @@ enum virtchnl2_event_codes { * @VIRTCHNL2_QUEUE_TYPE_P2P_RX_BUFFER: P2P RX buffer queue type. * @VIRTCHNL2_QUEUE_TYPE_MBX_TX: TX mailbox queue type. * @VIRTCHNL2_QUEUE_TYPE_MBX_RX: RX mailbox queue type. + * @VIRTCHNL2_QUEUE_TYPE_CNTR_NOTIF: RX queue to receive counter updates. * * Transmit and Receive queue types are valid in single as well as split queue * models. With Split Queue model, 2 additional types are introduced - @@ -467,6 +468,7 @@ enum virtchnl2_queue_type { */ VIRTCHNL2_QUEUE_TYPE_CPF_MBX_TX = 12, VIRTCHNL2_QUEUE_TYPE_CPF_MBX_RX = 13, + VIRTCHNL2_QUEUE_TYPE_CNTR_NOTIF = 14, }; /* Interrupt throttling rate index */ diff --git a/kcompat-generator.sh b/kcompat-generator.sh deleted file mode 100644 index 068c7ec..0000000 --- a/kcompat-generator.sh +++ /dev/null @@ -1,723 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0-only -# Copyright (C) 2019-2025 Intel Corporation - -set -Eeuo pipefail - -# This file generates HAVE_ and NEED_ defines for current kernel -# (or KSRC if provided). -# -# It does so by 'gen' function calls (see body of 'gen-devlink' for examples). -# 'gen' could look for various kinds of declarations in provided kernel headers, -# eg look for an enum in one of files specified and check if given enumeration -# (single value) is present. See 'Documentation' or comment above the 'gen' fun -# in the kcompat-lib.sh. - -# Why using bash/awk instead of an old/legacy approach? -# -# The aim is to replicate all the defines provided by human developers -# in the past. Additional bonus is the fact, that we no longer need to care -# about backports done by OS vendors (RHEL, SLES, ORACLE, UBUNTU, more to come). -# We will even work (compile) with only part of backports provided. -# -# To enable smooth transition, especially in time of late fixes, "old" method -# of providing flags should still work as usual. - -# End of intro. -# Find info about coding style/rules at the end of file. -# Most of the implementation is in kcompat-lib.sh, here are actual 'gen' calls. - -export LC_ALL=C -SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" -ORIG_CWD="$(pwd)" -trap 'rc=$?; echo >&2 "$(realpath "$ORIG_CWD/${BASH_SOURCE[0]}"):$LINENO: failed with rc: $rc"' ERR - -# shellcheck source=kcompat-lib.sh -source "$SCRIPT_DIR"/kcompat-lib.sh - -ARCH=$(uname -m) -IS_ARM= -if [ "$ARCH" == aarch64 ]; then - IS_ARM=1 -fi - -# DO NOT break gen calls below (via \), to make our compat code more grep-able, -# keep them also grouped, first by feature (like DEVLINK), then by .h filename -# finally, keep them sorted within a group (sort by flag name) - -# handy line of DOC copy-pasted form kcompat-lib.sh: -# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in - -function gen-aux() { - ah='include/linux/auxiliary_bus.h' - mh='include/linux/mod_devicetable.h' - HAVE_AUX_INT_REMOVE=0 - if config_has CONFIG_AUXILIARY_BUS && - check method remove of auxiliary_driver matches 'int' in "$ah" ; then - HAVE_AUX_INT_REMOVE=1 - fi - gen HAVE_AUXILIARY_DRIVER_INT_REMOVE if string "$HAVE_AUX_INT_REMOVE" equals 1 - - # generate HAVE_AUXILIARY_DEVICE_ID only for cases when it's disabled in .config - HAVE_AUX_DEV_ID=0 - if ! config_has CONFIG_AUXILIARY_BUS && check struct auxiliary_device_id in "$mh" ; then - HAVE_AUX_DEV_ID=1 - fi - gen HAVE_AUXILIARY_DEVICE_ID if string "$HAVE_AUX_DEV_ID" equals 1 -} - -function gen-bitfield() { - bf='include/linux/bitfield.h' - gen HAVE_INCLUDE_BITFIELD if macro FIELD_PREP in "$bf" - gen NEED_BITFIELD_FIELD_FIT if macro FIELD_FIT absent in "$bf" - gen NEED_BITFIELD_FIELD_MASK if fun field_mask absent in "$bf" - gen NEED_BITFIELD_FIELD_MAX if macro FIELD_MAX absent in "$bf" -} - -function gen-cleanup() { - ch='include/linux/cleanup.h' - dh='include/net/devlink.h' - mh='include/linux/mutex.h' - sh='include/linux/spinlock.h' - slabh='include/linux/slab.h' - rcuh='include/linux/rcupdate.h' - gen NEED_DEFINE_FREE if macro DEFINE_FREE absent in "$ch" - gen NEED___DEFINE_CLASS_IS_CONDITIONAL if macro __DEFINE_CLASS_IS_CONDITIONAL absent in "$ch" - gen NEED_DEFINE_GUARD_MUTEX if invocation of macro DEFINE_GUARD absent or lacks mutex_lock in "$mh" - gen NEED_LOCK_GUARD_FOR_RCU if invocation of macro DEFINE_LOCK_GUARD_0 absent or lacks rcu in "$rcuh" - gen NEED_DEFINE_FREE_KFREE if invocation of macro DEFINE_FREE absent or lacks kfree in "$slabh" - gen NEED_DEFINE_FREE_KVFREE if invocation of macro DEFINE_FREE absent or lacks kvfree in "$slabh" - gen NEED_LOCK_GUARD_FOR_SPINLOCK if invocation of macro DEFINE_LOCK_GUARD_1 absent or lacks spinlock in "$sh" - gen NEED_LOCK_GUARD_FOR_SPINLOCK_BH if invocation of macro DEFINE_LOCK_GUARD_1 absent or lacks spinlock_bh in "$sh" - gen NEED_DEFINE_GUARD_DEVLINK if invocation of macro DEFINE_GUARD absent or lacks devl_lock in "$dh" -} - -function gen-device() { - dh='include/linux/device.h' - dph='include/linux/dev_printk.h' - gen NEED_BUS_FIND_DEVICE_CONST_DATA if fun bus_find_device lacks 'const void \\*data' in "$dh" - gen NEED_DEV_LEVEL_ONCE if macro dev_level_once absent in "$dh" "$dph" -} - -function gen-devlink() { - dh='include/net/devlink.h' - gen HAVE_DEVLINK_ESWITCH_OPS_EXTACK if fun eswitch_mode_set matches extack in "$dh" - gen HAVE_DEVLINK_FLASH_UPDATE_BEGIN_END_NOTIFY if fun devlink_flash_update_begin_notify in "$dh" - gen HAVE_DEVLINK_FLASH_UPDATE_PARAMS if struct devlink_flash_update_params in "$dh" - gen HAVE_DEVLINK_FLASH_UPDATE_PARAMS_FW if struct devlink_flash_update_params matches 'struct firmware \\*fw' in "$dh" - gen HAVE_DEVLINK_FLASH_UPDATE_PARAMS_OVERWRITE_MASK if struct devlink_flash_update_params matches 'overwrite_mask' in "$dh" - gen HAVE_DEVLINK_HEALTH if enum devlink_health_reporter_state in "$dh" - gen HAVE_DEVLINK_HEALTH_OPS_EXTACK if method dump of devlink_health_reporter_ops matches extack in "$dh" - gen HAVE_DEVLINK_INFO_DRIVER_NAME_PUT if fun devlink_info_driver_name_put in "$dh" - gen HAVE_DEVLINK_PARAMS if method validate of devlink_param matches extack in "$dh" - gen HAVE_DEVLINK_PARAMS_GET_EXTACK if method get of devlink_param matches extack in "$dh" - gen HAVE_DEVLINK_PARAMS_PUBLISH if fun devlink_params_publish in "$dh" - gen HAVE_DEVLINK_PARAMS_SET_EXTACK if method set of devlink_param matches extack in "$dh" - gen HAVE_DEVLINK_PORT_NEW if method port_new of devlink_ops in "$dh" - gen HAVE_DEVLINK_PORT_OPS if struct devlink_port_ops in "$dh" - gen HAVE_DEVLINK_PORT_REGISTERED if struct devlink_port matches 'registered' in "$dh" - gen HAVE_DEVLINK_PORT_SPLIT if method port_split of '(devlink_ops|devlink_port_ops)' in "$dh" - gen HAVE_DEVLINK_PORT_SPLIT_EXTACK if method port_split of '(devlink_ops|devlink_port_ops)' matches extack in "$dh" - gen HAVE_DEVLINK_PORT_SPLIT_IN_OPS if method port_split of devlink_ops in "$dh" - gen HAVE_DEVLINK_PORT_SPLIT_IN_PORT_OPS if method port_split of devlink_port_ops in "$dh" - gen HAVE_DEVLINK_PORT_SPLIT_PORT_STRUCT if method port_split of '(devlink_ops|devlink_port_ops)' matches devlink_port in "$dh" - gen HAVE_DEVLINK_PORT_TYPE_ETH_HAS_NETDEV if fun devlink_port_type_eth_set matches 'struct net_device' in "$dh" - gen HAVE_DEVLINK_RATE_NODE_CREATE if fun devl_rate_node_create in "$dh" - # keep devlink_region_ops body in variable, to not look 4 times for - # exactly the same thing in big file - # please consider it as an example of "how to speed up if needed" - REGION_OPS="$(find-struct-decl devlink_region_ops "$dh")" - gen HAVE_DEVLINK_REGIONS if struct devlink_region_ops in - <<< "$REGION_OPS" - gen HAVE_DEVLINK_REGION_OPS_SNAPSHOT if fun snapshot in - <<< "$REGION_OPS" - gen HAVE_DEVLINK_REGION_OPS_SNAPSHOT_OPS if fun snapshot matches devlink_region_ops in - <<< "$REGION_OPS" - gen HAVE_DEVLINK_REGISTER_SETS_DEV if fun devlink_register matches 'struct device' in "$dh" - gen HAVE_DEVLINK_RELOAD_ENABLE_DISABLE if fun devlink_reload_enable in "$dh" - gen HAVE_DEVLINK_SET_FEATURES if fun devlink_set_features in "$dh" - gen HAVE_DEVL_HEALTH_REPORTER_DESTROY if fun devl_health_reporter_destroy in "$dh" - gen HAVE_DEVL_PORT_REGISTER if fun devl_port_register in "$dh" - gen HAVE_DEVL_PORT_REG_WITH_OPS_AND_UNREG if fun devl_port_register_with_ops in "$dh" - gen NEED_DEVLINK_FLASH_UPDATE_STATUS_NOTIFY if fun devlink_flash_update_status_notify absent in "$dh" - gen NEED_DEVLINK_FLASH_UPDATE_TIMEOUT_NOTIFY if fun devlink_flash_update_timeout_notify absent in "$dh" - gen NEED_DEVLINK_FMSG_DUMP_SKB if fun devlink_fmsg_dump_skb absent in "$dh" - gen NEED_DEVLINK_FMSG_PUT if macro devlink_fmsg_put absent in "$dh" - gen NEED_DEVLINK_HEALTH_DEFAULT_AUTO_RECOVER if fun devlink_health_reporter_create matches auto_recover in "$dh" - gen NEED_DEVLINK_REGION_CREATE_OPS if fun devlink_region_create lacks 'struct devlink_region_ops \\*ops' in "$dh" - gen NEED_DEVLINK_RESOURCES_UNREGISTER_NO_RESOURCE if fun devlink_resources_unregister matches 'struct devlink_resource \\*' in "$dh" - gen NEED_DEVLINK_TO_DEV if fun devlink_to_dev absent in "$dh" - gen NEED_DEVLINK_UNLOCKED_RESOURCE if fun devl_resource_size_get absent in "$dh" - gen NEED_DEVL_HEALTH_REPORTER_CREATE if fun devl_health_reporter_create absent in "$dh" - gen NEED_DEVL_HEALTH_REPORTER_CREATE_REMOVE_GRACEFUL_PERIOD if fun devl_health_reporter_create matches graceful_period in "$dh" - gen NEED_DEVL_LOCK if fun devl_lock absent in "$dh" - gen NEED_DEVL_PARAMS_REGISTER if fun devl_params_register absent in "$dh" - gen NEED_DEVL_PORT_REGISTER if fun devl_port_register absent in "$dh" - gen NEED_DEVL_REGION_CREATE if fun devl_region_create absent in "$dh" - gen NEED_DEVL_REGISTER if fun devl_register absent in "$dh" - gen NEED_DEVL_RESOURCE_REGISTER if fun devl_resource_register absent in "$dh" - - gen HAVE_DEVLINK_PORT_FLAVOUR_PCI_SF if enum devlink_port_flavour matches DEVLINK_PORT_FLAVOUR_PCI_SF in include/uapi/linux/devlink.h - gen HAVE_DEVLINK_RELOAD_ACTION_AND_LIMIT if enum devlink_reload_action matches DEVLINK_RELOAD_ACTION_FW_ACTIVATE in include/uapi/linux/devlink.h -} - -function gen-devres() { - dh='include/linux/device.h' - ddrh='include/linux/device/devres.h' - gen NEED_DEVM_KASPRINTF if fun devm_kasprintf absent in "$dh" "$ddrh" - gen NEED_DEVM_KCALLOC if fun devm_kcalloc absent in "$dh" "$ddrh" - gen NEED_DEVM_KFREE if fun devm_kfree absent in "$dh" "$ddrh" - gen NEED_DEVM_KMEMDUP if fun devm_kmemdup absent in "$dh" "$ddrh" - gen NEED_DEVM_KSTRDUP if fun devm_kstrdup absent in "$dh" "$ddrh" - gen NEED_DEVM_KVASPRINTF if fun devm_kvasprintf absent in "$dh" "$ddrh" - gen NEED_DEVM_KZALLOC if fun devm_kzalloc absent in "$dh" "$ddrh" -} - -function gen-dma() { - dma='include/linux/dma-mapping.h' - gen NEED_DMA_ATTRS_PTR if struct dma_attrs in include/linux/dma-attrs.h - gen NEED_DMA_ATTRS if fun dma_map_page_attrs absent in "$dma" -} - -function gen-dpll() { - dh='include/linux/dpll.h' - gen HAVE_DPLL_ESYNC if method esync_get of dpll_pin_ops in "$dh" - gen HAVE_DPLL_LOCK_STATUS_ERROR if method lock_status_get of dpll_device_ops matches status_error in "$dh" - gen HAVE_DPLL_PHASE_OFFSET if method phase_offset_get of dpll_pin_ops in "$dh" - gen HAVE_DPLL_PHASE_OFFSET_MONITOR if method phase_offset_monitor_set of dpll_device_ops in "$dh" - gen NEED_DPLL_NETDEV_PIN_SET if fun dpll_netdev_pin_set absent in "$dh" -} - -function gen-ethtool() { - eth='include/linux/ethtool.h' - nleth='include/linux/ethtool_netlink.h' - ueth='include/uapi/linux/ethtool.h' - unleth='include/uapi/linux/ethtool_netlink.h' - unlgeth='include/uapi/linux/ethtool_netlink_generated.h' - gen HAVE_ETHTOOL_COALESCE_EXTACK if method get_coalesce of ethtool_ops matches 'struct kernel_ethtool_coalesce \\*' in "$eth" - gen HAVE_ETHTOOL_EXTENDED_RINGPARAMS if method get_ringparam of ethtool_ops matches 'struct kernel_ethtool_ringparam \\*' in "$eth" - gen HAVE_ETHTOOL_FEC_HIST if method get_fec_stats of ethtool_ops matches 'struct ethtool_fec_hist \\*' in "$eth" - gen HAVE_ETHTOOL_GET_FEC_STATS_OPS if struct ethtool_ops matches '\\*get_fec_stats' in "$eth" - gen HAVE_ETHTOOL_GET_TS_STATS if struct ethtool_ops matches '\\*get_ts_stats' in "$eth" - gen HAVE_ETHTOOL_KEEE if struct ethtool_keee in "$eth" - gen HAVE_ETHTOOL_KERNEL_TS_INFO if struct kernel_ethtool_ts_info in "$eth" - gen HAVE_ETHTOOL_LINK_EXT_STATS if struct ethtool_ops matches '\\*get_link_ext_stats' in "$eth" - gen HAVE_ETHTOOL_PUTS if fun ethtool_puts in "$eth" - gen HAVE_ETHTOOL_RXFH_PARAM if struct ethtool_rxfh_param in "$eth" - gen HAVE_ETHTOOL_SUPPORTED_RING_PARAMS if struct ethtool_ops matches 'supported_ring_params' in "$eth" - gen NEED_ETHTOOL_RING_USE_TCP_DATA_SPLIT if enum ethtool_supported_ring_param matches ETHTOOL_RING_USE_TCP_DATA_SPLIT in "$eth" - gen NEED_ETHTOOL_SPRINTF if fun ethtool_sprintf absent in "$eth" - gen HAVE_ETHTOOL_FLOW_RSS if macro FLOW_RSS in "$ueth" - gen HAVE_ETHTOOL_LINK_MODE_FEC_NONE_BIT if enum ethtool_link_mode_bit_indices matches ETHTOOL_LINK_MODE_FEC_NONE_BIT in "$ueth" - gen NEED_ETHTOOL_LINK_MODE_BIT_INDICES if enum ethtool_link_mode_bit_indices absent in "$ueth" - - ETHTOOL_TCP_DATA_SPLIT=0 - if check anonymous enum matches ETHTOOL_TCP_DATA_SPLIT_UNKNOWN in "$unleth" || - check enum ethtool_tcp_data_split matches ETHTOOL_TCP_DATA_SPLIT_UNKNOWN in "$unlgeth"; then - ETHTOOL_TCP_DATA_SPLIT=1 - fi - gen HAVE_ETHTOOL_SUPPORT_TCP_DATA_SPLIT if string "$ETHTOOL_TCP_DATA_SPLIT" equals 1 -} - -function gen-exported-symbols() { - # The Module.symvers is a generated file that is found in the object - # directory, not the source directory. - symvers="${KOBJ}/Module.symvers" - gen HAVE_EXPORTED_IRQ_SET_AFFINITY if symbol irq_set_affinity matches vmlinux in "$symvers" -} - -function gen-filter() { - fh='include/linux/filter.h' - gen NEED_NO_NETDEV_PROG_XDP_WARN_ACTION if fun bpf_warn_invalid_xdp_action lacks 'struct net_device \\*' in "$fh" - gen NEED_XDP_DO_FLUSH if fun xdp_do_flush absent in "$fh" -} - -function gen-flow-dissector() { - aah='include/net/act_api.h' - fdh='include/net/flow_dissector.h' - fkh='include/net/flow_keys.h' - foh='include/net/flow_offload.h' - pch='include/net/pkt_cls.h' - sgh='include/net/sch_generic.h' - tmh='include/net/tc_act/tc_mirred.h' - - gen HAVE_FLOW_DISSECTOR_KEY_PPPOE if enum flow_dissector_key_id matches FLOW_DISSECTOR_KEY_PPPOE in "$fdh" "$fkh" - gen HAVE_FLOW_DISSECTOR_ICMP_ID if enum flow_dissector_key_icmp matches id in "$fdh" - - gen HAVE_FLOW_BLOCK_API if fun flow_block_cb_priv in "$foh" - - # following HAVE ... CVLAN flag is mistakenly named after an enum key, - # but guards code around function call that was introduced later - gen HAVE_FLOW_DISSECTOR_KEY_CVLAN if fun flow_rule_match_cvlan in "$foh" - gen HAVE_FLOW_MATCH_ICMP if struct flow_match_icmp in "$foh" - gen HAVE_TC_FLOW_INDIR_BLOCK_CLEANUP if fun flow_indr_dev_unregister matches 'void \\(\\*release\\)\\(void \\*cb_priv\\)' in "$foh" - gen HAVE_TC_FLOW_INDIR_DEV if fun flow_indr_dev_register in "$foh" - gen HAVE_TC_FLOW_RULE_INFRASTRUCTURE if struct flow_action in "$foh" - gen NEED_FLOW_BLOCK_BIND if enum '(flow_block_command|tc_block_command)' lacks FLOW_BLOCK_BIND in "$foh" "$pch" - gen NEED_FLOW_BLOCK_BINDER_TYPE if enum '(flow_block_binder_type|tcf_block_binder_type)' lacks FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS in "$foh" "$pch" - gen NEED_FLOW_BLOCK_CB_SETUP_SIMPLE if fun flow_block_cb_setup_simple absent in "$foh" - gen NEED_FLOW_CLS_OFFLOAD if struct flow_cls_offload absent in "$foh" - gen NEED_FLOW_MATCH if struct flow_match absent in "$foh" - - gen HAVE_TCF_BLOCK_CB_REGISTER_EXTACK if fun tcf_block_cb_register matches 'struct netlink_ext_ack \\*extack' in "$pch" - gen HAVE_TCF_EXTS_FOR_EACH_ACTION if macro tcf_exts_for_each_action in "$pch" - gen HAVE_TCF_EXTS_HAS_ACTION if fun tcf_exts_has_actions in "$pch" - gen HAVE_TCF_EXTS_TO_LIST if fun tcf_exts_to_list in "$pch" - - gen HAVE_TCF_BLOCK if fun '(tcf_block_cb_register|flow_block_cb_setup_simple)' in "$foh" "$pch" - gen HAVE_TC_CB_AND_SETUP_QDISC_MQPRIO if typedef '(tc_setup_cb_t|flow_setup_cb_t)' in "$aah" "$foh" "$sgh" - gen HAVE_TC_INDIR_BLOCK if fun '(flow_indr_dev_register|tc_indr_block_cb_register|flow_indr_block_cb_register)' in "$foh" "$pch" - gen HAVE_TC_SETUP_CLSFLOWER if struct '(tc_cls_flower_offload|flow_cls_offload)' in "$foh" "$pch" - - # Some drivers check HAVE_TCF_MIRRED_DEV and - # HAVE_TCF_MIRRED_EGRESS_REDIRECT directly, so we need to keep both - # the NEED_ and HAVE_ variants. - # - # Additionally, drivers check HAVE_TCF_MIRRED_REDIRECT and expect it - # to be true even after the rename to is_tcf_mirred_egress_redirect. - gen HAVE_TCF_MIRRED_DEV if fun tcf_mirred_dev in "$tmh" - gen HAVE_TCF_MIRRED_EGRESS_REDIRECT if fun is_tcf_mirred_egress_redirect in "$tmh" - gen HAVE_TCF_MIRRED_REDIRECT if fun '(is_tcf_mirred_egress_redirect|is_tcf_mirred_redirect)' in "$tmh" - gen NEED_TCF_MIRRED_DEV if fun tcf_mirred_dev absent in "$tmh" - gen NEED_TCF_MIRRED_EGRESS_REDIRECT if fun is_tcf_mirred_egress_redirect absent in "$tmh" -} - -function gen-gnss() { - cdh='include/linux/cdev.h' - clh='include/linux/device/class.h' - dh='include/linux/device.h' - gh='include/linux/gnss.h' - th='include/uapi/linux/types.h' - fh='include/linux/fs.h' - - gen HAVE_CDEV_DEVICE if fun cdev_device_add in "$cdh" - gen HAVE_DEV_UEVENT_CONST if method dev_uevent of class matches '(const|RH_KABI_CONST) struct device' in "$clh" "$dh" - gen HAVE_NO_LLSEEK if fun no_llseek in "$fh" - gen HAVE_STREAM_OPEN if fun stream_open in "$fh" - - NEED_CLASS_CREATE=0 - if check fun class_create matches 'owner' in "$clh" "$dh" || - check macro class_create matches 'owner' in "$clh" "$dh" ; then - NEED_CLASS_CREATE=1 - fi - gen NEED_CLASS_CREATE_WITHOUT_OWNER if string "$NEED_CLASS_CREATE" equals 1 - - HAVE_GNSS_MODULE=0 - if check struct gnss_device in "$gh" ; then - if ! config_has CONFIG_SUSE_KERNEL || config_has CONFIG_SUSE_PRODUCT_SLFO ; then - HAVE_GNSS_MODULE=1 - fi - fi - gen HAVE_GNSS_MODULE if string "$HAVE_GNSS_MODULE" equals 1 - - gen HAVE_POLL_T if typedef __poll_t in "$th" -} - -function gen-mdev() { - mdevh='include/linux/mdev.h' - - gen HAVE_DEV_IN_MDEV_API if method probe of mdev_driver matches 'struct device \\*' in "$mdevh" - gen HAVE_KOBJ_IN_MDEV_PARENT_OPS_CREATE if method create of mdev_parent_ops matches 'struct kobject \\*' in "$mdevh" -} - -function gen-mdio() { - mdioh='include/linux/mdio.h' - - gen HAVE_MII_EEE_CAP1_MOD_LINKMODE if fun mii_eee_cap1_mod_linkmode_t in "$mdioh" -} - -function gen-mm() { - slabh='include/linux/slab.h' - - gen NEED_KREALLOC_ARRAY if fun krealloc_array absent in "$slabh" - - HAVE_KMEM_CACHE_ALLOC_LRU=0 - check macro kmem_cache_alloc_lru in "$slabh" && HAVE_KMEM_CACHE_ALLOC_LRU=1 - check fun kmem_cache_alloc_lru in "$slabh" && HAVE_KMEM_CACHE_ALLOC_LRU=1 - gen NEED_KMEM_CACHE_ALLOC_LRU if string "$HAVE_KMEM_CACHE_ALLOC_LRU" equals 0 -} - -function gen-netdevice() { - ndh='include/linux/netdevice.h' - gen HAVE_NDO_BRIDGE_SETLINK_EXTACK if method ndo_bridge_setlink of net_device_ops matches 'struct netlink_ext_ack \\*extack' in "$ndh" - gen HAVE_NDO_ETH_IOCTL if fun ndo_eth_ioctl in "$ndh" - gen HAVE_NDO_EXTENDED_SET_TX_MAXRATE if method ndo_set_tx_maxrate of net_device_ops_extended in "$ndh" - gen HAVE_NDO_FDB_ADD_EXTACK if method ndo_fdb_add of net_device_ops matches 'struct netlink_ext_ack \\*extack' in "$ndh" - gen HAVE_NDO_FDB_ADD_NOTIFIED if method ndo_fdb_add of net_device_ops matches 'bool \\*notified' in "$ndh" - gen HAVE_NDO_FDB_ADD_VID if method ndo_fdb_add of net_device_ops matches 'u16 vid' in "$ndh" - gen HAVE_NDO_FDB_DEL_EXTACK if method ndo_fdb_del of net_device_ops matches 'struct netlink_ext_ack \\*extack' in "$ndh" - gen HAVE_NDO_FDB_DEL_NOTIFIED if method ndo_fdb_del of net_device_ops matches 'bool \\*notified' in "$ndh" - gen HAVE_NDO_GET_DEVLINK_PORT if method ndo_get_devlink_port of net_device_ops in "$ndh" - gen HAVE_NDO_SETUP_TC_CHAIN_INDEX if method ndo_setup_tc of net_device_ops matches 'u32 chain_index' in "$ndh" - gen HAVE_NDO_SETUP_TC_REMOVE_TC_TO_NETDEV if method '(ndo_setup_tc|ndo_setup_tc_rh)' of '(net_device_ops|netdevice_ops_extended)' matches 'void \\*type_data' in "$ndh" - gen HAVE_NDO_UDP_TUNNEL_CALLBACK if method ndo_udp_tunnel_add of net_device_ops in "$ndh" - gen HAVE_NETDEV_EXTENDED_MIN_MAX_MTU if struct net_device_extended matches min_mtu in "$ndh" - gen HAVE_NETDEV_FCOE_MTU if struct net_device matches fcoe_mtu in "$ndh" - gen HAVE_NETDEV_IRQ_AFFINITY_AND_ARFS if struct net_device matches irq_affinity_auto in "$ndh" - gen HAVE_NETDEV_MIN_MAX_MTU if struct net_device matches min_mtu in "$ndh" - gen HAVE_NETIF_SET_TSO_MAX if fun netif_set_tso_max_size in "$ndh" - gen HAVE_RHEL7_NETDEV_OPS_EXT_NDO_SETUP_TC if method ndo_setup_tc_rh of net_device_ops_extended in "$ndh" - gen HAVE_SET_NETDEV_DEVLINK_PORT if macro SET_NETDEV_DEVLINK_PORT in "$ndh" - gen NEED_NETDEV_TX_SENT_QUEUE if fun __netdev_tx_sent_queue absent in "$ndh" - gen NEED_NETIF_NAPI_ADD_NO_WEIGHT if fun netif_napi_add matches 'int weight' in "$ndh" - gen NEED_NET_PREFETCH if fun net_prefetch absent in "$ndh" - gen NEED_XDP_FEATURES if enum netdev_xdp_act absent in include/uapi/linux/netdev.h -} - -function gen-netif() { - gen HAVE_GENEVE_TYPE if fun netif_is_geneve in include/net/geneve.h - gen HAVE_GRETAP_TYPE if fun netif_is_gretap in include/net/gre.h - gen HAVE_GTP_SUPPORT if fun netif_is_gtp in include/net/gtp.h - gen HAVE_NETIF_SUBQUEUE_MAYBE_STOP if macro netif_subqueue_maybe_stop in include/net/netdev_queues.h - gen HAVE_VXLAN_TYPE if fun netif_is_vxlan in include/net/vxlan.h -} - -function gen-packing() { - lph='include/linux/packing.h' - HAVE_PACK_FIELDS=0 - if config_has CONFIG_PACKING && check macro pack_fields in "$lph" ; then - HAVE_PACK_FIELDS=1 - fi - gen HAVE_PACK_FIELDS if string "$HAVE_PACK_FIELDS" equals 1 -} - -function gen-pci() { - pcih='include/linux/pci.h' - gen HAVE_PCI_MSIX_ALLOC_IRQ_AT if fun pci_msix_alloc_irq_at in "$pcih" - gen HAVE_PCI_MSIX_CAN_ALLOC_DYN if fun pci_msix_can_alloc_dyn in "$pcih" - gen HAVE_PCI_MSIX_FREE_IRQ if fun pci_msix_free_irq in "$pcih" - gen HAVE_PER_VF_MSIX_SYSFS if method sriov_set_msix_vec_count of pci_driver in "$pcih" - gen HAVE_STRUCT_PCI_DEV_PTM_CAP if struct pci_dev matches ptm_cap in "$pcih" - gen HAVE_STRUCT_PCI_DEV_PTM_ENABLED if struct pci_dev matches ptm_enabled in "$pcih" - gen NEED_PCIE_FLR if fun pcie_flr absent in "$pcih" - gen NEED_PCIE_FLR_RETVAL if fun pcie_flr lacks 'int pcie_flr' in "$pcih" - gen NEED_PCIE_PTM_ENABLED if fun pcie_ptm_enabled absent in "$pcih" - gen NEED_PCI_DISABLE_PTM if fun pci_disable_ptm absent in "$pcih" - gen NEED_PCI_ENABLE_PTM if fun pci_enable_ptm absent in "$pcih" -} - -function gen-ptp() { - classifyh='include/linux/ptp_classify.h' - clockh='include/linux/ptp_clock_kernel.h' - timekeepingh='include/linux/timekeeping.h' - uapih='include/uapi/linux/ptp_clock.h' - gen HAVE_PTP_CSID_X86_ART if enum clocksource_ids matches CSID_X86_ART in include/linux/clocksource_ids.h - gen NEED_PTP_CLASSIFY_RAW if fun ptp_classify_raw absent in "$classifyh" - gen NEED_PTP_PARSE_HEADER if fun ptp_parse_header absent in "$classifyh" - gen HAVE_PTP_CANCEL_WORKER_SYNC if fun ptp_cancel_worker_sync in "$clockh" - gen HAVE_PTP_CLOCK_DO_AUX_WORK if method do_aux_work of ptp_clock_info in "$clockh" - gen HAVE_PTP_CLOCK_INFO_ADJFINE if method adjfine of ptp_clock_info in "$clockh" - gen HAVE_PTP_CLOCK_INFO_GETTIME64 if method gettime64 of ptp_clock_info in "$clockh" - gen HAVE_PTP_CLOCK_INFO_GETTIMEX64 if method gettimex64 of ptp_clock_info in "$clockh" - gen HAVE_PTP_FIND_PIN_UNLOCKED if fun ptp_find_pin_unlocked in "$clockh" - gen HAVE_PTP_SUPPORTED_EXTTS_FLAGS if struct ptp_clock_info matches supported_extts_flags in "$clockh" - gen HAVE_PTP_SUPPORTED_PEROUT_FLAGS if struct ptp_clock_info matches supported_perout_flags in "$clockh" - gen NEED_DIFF_BY_SCALED_PPM if fun diff_by_scaled_ppm absent in "$clockh" - gen NEED_PTP_SYSTEM_TIMESTAMP if fun ptp_read_system_prets absent in "$clockh" - gen HAVE_PTP_SYS_COUNTERVAL_CSID if struct system_counterval_t matches clocksource_ids in "$timekeepingh" - gen HAVE_PTP_TX_ONESTEP_P2P if enum hwtstamp_tx_types matches HWTSTAMP_TX_ONESTEP_P2P in include/uapi/linux/net_tstamp.h - gen HAVE_PTP_SYS_OFFSET_EXTENDED_IOCTL if macro PTP_SYS_OFFSET_EXTENDED in "$uapih" - - # aarch64 requires additional function to enable cross timestamping - if config_has CONFIG_ARM64 && - (check fun arch_timer_wrap_counter in include/clocksource/arm_arch_timer.h || - check struct system_counterval_t matches clocksource_ids in "$timekeepingh") ; then - HAVE_CROSS_TSTAMP=1 - elif config_has CONFIG_X86 && - (check fun convert_art_ns_to_tsc in arch/x86/include/asm/tsc.h || - check enum clocksource_ids matches CSID_X86_ART in include/linux/clocksource_ids.h) ; then - HAVE_CROSS_TSTAMP=1 - else - HAVE_CROSS_TSTAMP=0 - fi - gen HAVE_PTP_CROSSTIMESTAMP if string "${HAVE_CROSS_TSTAMP}" equals 1 -} - -function gen-stddef() { - stddef='include/linux/stddef.h' - ustddef='include/uapi/linux/stddef.h' - gen HAVE_STDDEF_OFFSETTOEND if macro offsetofend in "$stddef" - gen NEED_DECLARE_FLEX_ARRAY if macro DECLARE_FLEX_ARRAY absent in "$stddef" - gen NEED_STRUCT_GROUP if macro struct_group absent in "$stddef" - gen NEED___STRUCT_GROUP if macro __struct_group absent in "$ustddef" -} - -function gen-vdcm() { - gen NEED_EVENTFD_SIGNAL_NO_COUNTER if fun eventfd_signal matches '__u64 n' in include/linux/eventfd.h -} - -function gen-vfio() { - # PASID_SUPPORT depends on multiple different functions existing - PASID_SUPPORT=0 - if check fun mdev_set_iommu_device in include/linux/mdev.h && - check fun vfio_group_iommu_domain in include/linux/vfio.h ; then - PASID_SUPPORT=1 - fi - gen HAVE_PASID_SUPPORT if string "${PASID_SUPPORT}" equals 1 - - gen HAVE_VFIO_FREE_DEV if fun vfio_free_device in include/linux/vfio.h - gen HAVE_LMV1_SUPPORT if macro VFIO_REGION_TYPE_MIGRATION in include/uapi/linux/vfio.h -} - -function gen-other() { - pciaerh='include/linux/aer.h' - ush='include/linux/u64_stats_sync.h' - fsh='include/linux/fortify-string.h' - cth='include/linux/compiler_types.h' - ch='include/linux/compiler.h' - gen HAVE_X86_STEPPING if struct cpuinfo_x86 matches x86_stepping in arch/x86/include/asm/processor.h - gen HAVE_PCI_ENABLE_PCIE_ERROR_REPORTING if fun pci_enable_pcie_error_reporting in "$pciaerh" - gen NEED_PCI_AER_CLEAR_NONFATAL_STATUS if fun pci_aer_clear_nonfatal_status absent in "$pciaerh" - gen NEED_BITMAP_COPY_CLEAR_TAIL if fun bitmap_copy_clear_tail absent in include/linux/bitmap.h - gen NEED_BITMAP_FROM_ARR32 if fun bitmap_from_arr32 absent in include/linux/bitmap.h - gen NEED_BITMAP_TO_ARR32 if fun bitmap_to_arr32 absent in include/linux/bitmap.h - gen NEED_ASSIGN_BIT if fun assign_bit absent in include/linux/bitops.h - gen NEED_STATIC_ASSERT if macro static_assert absent in include/linux/build_bug.h - gen NEED____ADDRESSABLE if macro ___ADDRESSABLE absent in "$ch" - # special case for kernels 6.2 - 6.6 and __struct_size macro - # there is an implicit dependency on CONFIG_FORTIFY_SOURCE config option and inclusion - # of 'forify-string.h' header (which includes that macro definition). - __STRUCT_SIZE_NEEDED=0 - if ! config_has CONFIG_FORTIFY_SOURCE && check macro __struct_size in "$fsh" ; then - __STRUCT_SIZE_NEEDED=1 - fi - if [ ${__STRUCT_SIZE_NEEDED} -eq 0 ] && check macro __struct_size absent in "$cth" "$fsh"; then - __STRUCT_SIZE_NEEDED=1 - fi - gen NEED___STRUCT_SIZE if string "${__STRUCT_SIZE_NEEDED}" equals 1 - gen HAVE_COMPLETION_RAW_SPINLOCK if struct completion matches 'struct swait_queue_head' in include/linux/completion.h - gen NEED_IS_CONSTEXPR if macro __is_constexpr absent in include/linux/const.h include/linux/minmax.h include/linux/kernel.h - gen NEED_DEBUGFS_LOOKUP if fun debugfs_lookup absent in include/linux/debugfs.h - gen NEED_DEBUGFS_LOOKUP_AND_REMOVE if fun debugfs_lookup_and_remove absent in include/linux/debugfs.h - gen NEED_DIM_END_SAMPLE_BY_POINTER if fun net_dim matches 'struct dim_sample end_sample' in include/linux/dim.h - gen NEED_ETH_GET_HEADLEN if fun eth_get_headlen absent in include/linux/etherdevice.h - gen NEED_ETH_GET_HEADLEN_NET_DEVICE_ARG if fun eth_get_headlen lacks 'struct net_device \\*' in include/linux/etherdevice.h - gen NEED_ETH_HW_ADDR_SET if fun eth_hw_addr_set absent in include/linux/etherdevice.h - gen NEED_FIND_NEXT_BIT_WRAP if fun find_next_bit_wrap absent in include/linux/find.h - gen HAVE_FILE_IN_SEQ_FILE if struct seq_file matches 'struct file' in include/linux/fs.h - gen NEED_FS_FILE_DENTRY if fun file_dentry absent in include/linux/fs.h - gen HAVE_HWMON_DEVICE_REGISTER_WITH_INFO if fun hwmon_device_register_with_info in include/linux/hwmon.h - gen NEED_HWMON_CHANNEL_INFO if macro HWMON_CHANNEL_INFO absent in include/linux/hwmon.h - gen NEED_ETH_TYPE_VLAN if fun eth_type_vlan absent in include/linux/if_vlan.h - gen HAVE_IOMMU_DEV_FEAT_AUX if enum iommu_dev_features matches IOMMU_DEV_FEAT_AUX in include/linux/iommu.h - gen NEED_READ_POLL_TIMEOUT if macro read_poll_timeout absent in include/linux/iopoll.h - gen NEED_READ_POLL_TIMEOUT_ATOMIC if macro read_poll_timeout_atomic absent in include/linux/iopoll.h - gen NEED_DEFINE_STATIC_KEY_FALSE if macro DEFINE_STATIC_KEY_FALSE absent in include/linux/jump_label.h - gen NEED_STATIC_BRANCH_LIKELY if macro static_branch_likely absent in include/linux/jump_label.h - gen HAVE_STRUCT_STATIC_KEY_FALSE if struct static_key_false in include/linux/jump_label.h include/linux/jump_label_type.h - gen NEED_DECLARE_STATIC_KEY_FALSE if macro DECLARE_STATIC_KEY_FALSE absent in include/linux/jump_label.h include/linux/jump_label_type.h - gen NEED_LOWER_16_BITS if macro lower_16_bits absent in include/linux/kernel.h - gen NEED_UPPER_16_BITS if macro upper_16_bits absent in include/linux/kernel.h - gen HAVE_LINKMODE if fun linkmode_zero in include/linux/linkmode.h - gen NEED_LINKMODE_SET_BIT_ARRAY if fun linkmode_set_bit_array absent in include/linux/linkmode.h - gen NEED_LINKMODE_ZERO if fun linkmode_zero absent in include/linux/linkmode.h - gen NEED_LIST_COUNT_NODES if fun list_count_nodes absent in include/linux/list.h - - # On aarch64 RHEL systems, mul_u64_u64_div_u64 appears to be declared - # in math64 header, but is not provided by kernel - # so on these systems, set it to need anyway. - NEED_MUL_U64=0 - if [ "$IS_ARM" ] || check fun mul_u64_u64_div_u64 absent in include/linux/math64.h ; then - NEED_MUL_U64=1 - fi - gen NEED_MUL_U64_U64_DIV_U64 if string "${NEED_MUL_U64}" equals 1 - - gen NEED_DIV_U64_ROUND_CLOSEST if macro DIV_U64_ROUND_CLOSEST absent in include/linux/math64.h - gen NEED_DIV_U64_ROUND_UP if macro DIV_U64_ROUND_UP absent in include/linux/math64.h - gen NEED_ROUNDUP_U64 if fun roundup_u64 absent in include/linux/math64.h - gen HAVE_MDEV_GET_DRVDATA if fun mdev_get_drvdata in include/linux/mdev.h - gen HAVE_MDEV_REGISTER_PARENT if fun mdev_register_parent in include/linux/mdev.h - gen HAVE_VM_FLAGS_API if fun vm_flags_init in include/linux/mm.h - gen HAVE_NL_SET_ERR_MSG_FMT if macro NL_SET_ERR_MSG_FMT in include/linux/netlink.h - gen NEED_DEFINE_SIMPLE_DEV_OPS if macro DEFINE_SIMPLE_DEV_OPS absent in include/linux/pm.h - gen NEED_PM_SLEEP_PTR if macro pm_sleep_ptr absent in include/linux/pm.h - gen NEED_DEV_PM_DOMAIN_ATTACH if fun dev_pm_domain_attach absent in include/linux/pm_domain.h include/linux/pm.h - gen NEED_DEV_PM_DOMAIN_DETACH if fun dev_pm_domain_detach absent in include/linux/pm_domain.h include/linux/pm.h - gen NEED_RADIX_TREE_EMPTY if fun radix_tree_empty absent in include/linux/radix-tree.h - gen HAVE_LINUX_REFCOUNT_HEADER if fun refcount_inc in include/linux/refcount.h - gen NEED_SCHED_PARAM if struct sched_param absent in include/linux/sched.h - gen NEED_SET_SCHED_FIFO if fun sched_set_fifo absent in include/linux/sched.h - gen NEED_RT_H if macro MAX_RT_PRIO absent in include/linux/sched/prio.h - gen HAVE_SKB_CSUM_IS_SCTP if fun skb_csum_is_sctp in include/linux/skbuff.h - gen NEED_DEV_PAGE_IS_REUSABLE if fun dev_page_is_reusable absent in include/linux/skbuff.h - gen NEED_NAPI_ALLOC_SKB if fun __napi_alloc_skb in include/linux/skbuff.h - gen NEED_NAPI_BUILD_SKB if fun napi_build_skb absent in include/linux/skbuff.h - gen NEED_SKB_FRAG_OFF if fun skb_frag_off absent in include/linux/skbuff.h - gen NEED_SKB_FRAG_OFF_ADD if fun skb_frag_off_add absent in include/linux/skbuff.h - gen NEED_SYSFS_MATCH_STRING if macro sysfs_match_string absent in include/linux/string.h - gen HAVE_STRING_CHOICES_H if fun str_enabled_disabled in include/linux/string_choices.h - gen NEED_STR_ENABLED_DISABLED if fun str_enabled_disabled absent in include/linux/string_choices.h include/linux/string_helpers.h - gen HAVE_STRING_HELPERS_H if enum string_size_units in include/linux/string_helpers.h - gen NEED_SYSFS_EMIT if fun sysfs_emit absent in include/linux/sysfs.h - gen HAVE_NON_CONST_CYCLECOUNTER if method read of cyclecounter lacks const in include/linux/timecounter.h - gen NEED_TIMER_CONTAINER_OF if macro timer_container_of absent in include/linux/timer.h - gen NEED_TIMER_DELETE if fun timer_delete absent in include/linux/timer.h - gen HAVE_TRACE_ENABLED_SUPPORT if implementation of macro __DECLARE_TRACE matches 'trace_##name##_enabled' in include/linux/tracepoint.h - gen HAVE_TTY_OP_WRITE_SIZE_T if method write of tty_operations matches size_t in include/linux/tty_driver.h - gen HAVE_U64_STATS_FETCH_BEGIN_IRQ if fun u64_stats_fetch_begin_irq in "$ush" - gen HAVE_U64_STATS_FETCH_RETRY_IRQ if fun u64_stats_fetch_retry_irq in "$ush" - gen NEED_U64_STATS_READ if fun u64_stats_read absent in "$ush" - gen NEED_U64_STATS_SET if fun u64_stats_set absent in "$ush" - gen HAVE_XARRAY_API if macro DEFINE_XARRAY in include/linux/xarray.h - gen HAVE_TC_FLOWER_ENC if enum flow_dissector_key_id matches FLOW_DISSECTOR_KEY_ENC_CONTROL in include/net/flow_dissector.h - gen HAVE_TC_FLOWER_VLAN_IN_TAGS if enum flow_dissector_key_id matches FLOW_DISSECTOR_KEY_VLANID in include/net/flow_dissector.h - gen HAVE_NET_RPS_H if macro RPS_NO_FILTER in include/net/rps.h - gen HAVE_UDP_TUNNEL_NIC_INFO_MAY_SLEEP if enum udp_tunnel_nic_info_flags matches UDP_TUNNEL_NIC_INFO_MAY_SLEEP in include/net/udp_tunnel.h - gen NEED_XDP_CONVERT_BUFF_TO_FRAME if fun xdp_convert_buff_to_frame absent in include/net/xdp.h - gen NEED_XSK_BUFF_DMA_SYNC_FOR_CPU_NO_POOL if fun xsk_buff_dma_sync_for_cpu matches 'struct xsk_buff_pool' in include/net/xdp_sock_drv.h - gen HAVE_ASSIGN_STR_2_PARAMS if macro __assign_str matches src in include/trace/stages/stage6_event_callback.h include/trace/trace_events.h include/trace/ftrace.h - - HAVE_LINUX_UNALIGNED=0 - if [ -n "$(filter-out-bad-files include/linux/unaligned.h)" ]; then - HAVE_LINUX_UNALIGNED=1 - fi - gen HAVE_LINUX_UNALIGNED_HEADER if string "${HAVE_LINUX_UNALIGNED}" equals 1 - - HAVE_LINUX_BITS=0 - if [ -n "$(filter-out-bad-files include/linux/bits.h)" ]; then - HAVE_LINUX_BITS=1 - fi - gen HAVE_LINUX_BITS_HEADER if string "${HAVE_LINUX_BITS}" equals 1 - - HAVE_LINUX_REFCOUNT_TYPES=0 - if [ -n "$(filter-out-bad-files include/linux/refcount_types.h)" ]; then - HAVE_LINUX_REFCOUNT_TYPES=1 - fi - gen HAVE_LINUX_REFCOUNT_TYPES_HEADER if string "${HAVE_LINUX_REFCOUNT_TYPES}" equals 1 -} - -# all the generations, extracted from main() to keep normal code and various -# prep separated -function gen-all() { - if config_has CONFIG_NET_DEVLINK; then - gen-devlink - fi - gen-netdevice - # code above is covered by unit_tests/test_gold.sh - if [ -n "${JUST_UNIT_TESTING-}" ]; then - return - fi - gen-aux - gen-bitfield - gen-cleanup - gen-device - gen-devres - gen-dma - gen-dpll - gen-ethtool - gen-exported-symbols - gen-filter - gen-flow-dissector - gen-gnss - gen-mdev - gen-mdio - gen-mm - gen-netif - gen-packing - gen-pci - gen-ptp - gen-stddef - gen-vdcm - gen-vfio - gen-other -} - -function main() { - if ! [ -d "${KSRC-}" ]; then - echo >&2 "env KSRC=${KSRC-} does not exist or is not a directory" - exit 11 - fi - - # Assume KOBJ is the same as KSRC if not set. - if [ -z "${KOBJ-}" ]; then - KOBJ="${KSRC-}" - fi - - # we need some flags from .config or (autoconf.h), try to find it - if [ -z "${CONFIG_FILE-}" ]; then - find_config_file - - if [ -z ${CONFIG_FILE-} ]; then - echo >&2 "unable to locate a config file at KOBJ=${KOBJ}. please set CONFIG_FILE to the kernel configuration file." - exit 10 - fi - fi - - if [ ! -f "${CONFIG_FILE-}" ]; then - echo >&2 ".config passed in by env CONFIG_FILE=${CONFIG_FILE} does not exist or is not a file" - exit 9 - fi - CONFIG_FILE=$(realpath "${CONFIG_FILE-}") - - # check if caller (like our makefile) wants to redirect output to file - if [ -n "${OUT-}" ]; then - - # in case OUT exists, we don't want to overwrite it, instead - # write to a temporary copy. - if [ -s "${OUT}" ]; then - TMP_OUT="$(mktemp "${OUT}.XXX")" - trap "rm -f '${TMP_OUT}'" EXIT - - REAL_OUT="${OUT}" - OUT="${TMP_OUT}" - fi - - exec > "$OUT" - # all stdout goes to OUT since now - echo "/* Autogenerated for KSRC=${KSRC-} via $(basename "$0") */" - fi - - cd "${KSRC}" - - # check if KSRC was ok/if we are in proper place to look for headers - if [ -z "$(filter-out-bad-files include/linux/kernel.h)" ]; then - echo >&2 "seems that there are no kernel includes placed in KSRC=${KSRC} - pwd=$(pwd); ls -l:" - ls -l >&2 - exit 8 - fi - - if [ -z ${UNIFDEF_MODE-} ]; then - echo "#ifndef _KCOMPAT_GENERATED_DEFS_H_" - echo "#define _KCOMPAT_GENERATED_DEFS_H_" - fi - - gen-all - - if [ -z ${UNIFDEF_MODE-} ]; then - echo "#endif /* _KCOMPAT_GENERATED_DEFS_H_ */" - fi - - if [ -n "${OUT-}" ]; then - cd "$ORIG_CWD" - - # Compare and see if anything changed. This avoids updating - # mtime of the file. - if [ -n "${REAL_OUT-}" ]; then - if cmp --silent "${REAL_OUT}" "${TMP_OUT}"; then - # exit now, skipping print of the output since - # there were no changes. the trap should - # cleanup TMP_OUT - exit 0 - fi - - mv -f "${TMP_OUT}" "${REAL_OUT}" - OUT="${REAL_OUT}" - fi - - # dump output, will be visible in CI - if [ -n "${JUST_UNIT_TESTING-}${QUIET_COMPAT-}" ]; then - return - fi - cat -n "$OUT" >&2 - fi -} - -main - -# Coding style: -# - rely on `set -e` handling as much as possible, so: -# - do not use <(bash process substitution) - it breaks error handling; -# - do not put substantial logic in `if`-like statement - it disables error -# handling inside of the conditional (`if big-fun call; then` is substantial) -# - make shellcheck happy - https://www.shellcheck.net -# -# That enables us to move processing out of `if` or `... && ...` statements, -# what finally means that bash error handling (`set -e`) would break on errors. diff --git a/kcompat-lib.sh b/kcompat-lib.sh deleted file mode 100644 index 5f30f1b..0000000 --- a/kcompat-lib.sh +++ /dev/null @@ -1,490 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0-only -# Copyright (C) 2019-2025 Intel Corporation - -# to be sourced - -# General shell helpers - -# exit with non-zero exit code; if there is only one param: -# exit with msg $1 and exit code from last command (or 99 if = 0) -# otherwise, exit with $1 and use remaining arguments as msg -function die() { - rc=$? - if [ $# -gt 1 ]; then - rc="$1" - shift - fi - [ "$rc" -ne 0 ] || rc=99 - echo >&2 "$@" - exit $rc -} - -# filter out paths that are not files -# input $@, output via echo; -# note: pass `-` for stdin -# note: outputs nothing if all input files are "bad" (eg. not existing), but it -# is left for caller to decide if this is an erorr condition; -# note: whitespaces are considered "bad" as part of filename, it's an error. -function filter-out-bad-files() { - if [[ $# = 1 && "$1" = '-' ]]; then - echo - - return 0 - fi - if [ $# = 0 ]; then - die 10 "no files passed, use '-' when reading from pipe (|)" - fi - local any=0 diagmsgs=/dev/stderr re=$'[\t \n]' - [ -n "${QUIET_COMPAT-}" ] && diagmsgs=/dev/null - for x in "$@"; do - if [ -e "$x" ]; then - if [[ "$x" =~ $re ]]; then - die 11 "err: filename contains whitespaces: $x." - fi - echo "$x" - any=1 - else - echo >&"$diagmsgs" filtering "$x" out - fi - done - if [ $any = 0 ]; then - echo >&"$diagmsgs" 'all files (for given query) filtered out' - fi -} - -# Basics of regexp explained, as a reference for mostly-C programmers: -# (bash) "regexp-$VAR-regexp" - bash' VARs are placed into "QUOTED" strings -# /\);?$/ - match end of function declaration, $ is end of string -# ^[ \t]* - (heuristic), anything but comment, eg to exclude function docs -# /STH/, /END/ - (awk), print all lines sice STH matched, up to END, inclusive - -# "Whitespace only" -WB='[ \t\n]' - -# Helpers below print the thing that is looked for, for further grep'ping/etc. -# That simplifies process of excluding comments or spares us state machine impl. -# -# We take advantage of current/common linux codebase formatting here. -# -# Functions in this section require input file/s passed as args -# (usually one, but more could be supplied in case of renames in kernel), -# '-' could be used as an (only) file argument to read from stdin/pipe. - -# wrapper over find-something-decl() functions below, to avoid repetition -# pass $what as $1, $end as $2, and $files to look in as rest of args -function find-decl() { - test $# -ge 3 # ensure that there are at least 3 params - local what end files - what="$1" - end="$2" - shift 2 - files="$(filter-out-bad-files "$@")" || die - if [ -z "$files" ]; then - return 0 - fi - # shellcheck disable=SC2086 - awk " - /^$WB*\*/ {next} - $what, $end - " $files -} - -# yield $1 function declaration (signature), don't pass return type in $1 -# looks only in files specified ($2, $3...) -function find-fun-decl() { - test $# -ge 2 - local what end - what="/$WB*([(]\*)?$1$WB*($|[()])/" - end='/\);?$/' - shift - find-decl "$what" "$end" "$@" -} - -# yield $1 enum declaration (type/body) -function find-enum-decl() { - test $# -ge 2 - local what end - what="/^$WB*enum$WB+$1"' \{$/' - end='/\};$/' - shift - find-decl "$what" "$end" "$@" -} - -# yield anonymous enum declaration (type/body) -function find-anon-enum-decl() { - test $# -ge 2 - local what end - what="/^$WB*enum$WB+"'\{$/' - end='/\};$/' - shift - find-decl "$what" "$end" "$@" -} - -# yield $1 struct declaration (type/body) -function find-struct-decl() { - test $# -ge 2 - local what end - what="/^$WB*struct$WB+$1"' \{$/' - end='/^\};$/' # that's (^) different from enum-decl - shift - find-decl "$what" "$end" "$@" -} - -# yield first line of $1 macro definition -function find-macro-decl() { - test $# -ge 2 - local what end - # only unindented defines, only whole-word match - what="/^#define$WB+$1"'([ \t\(]|$)/' - end=1 # only first line; use find-macro-implementation-decl for full body - shift - find-decl "$what" "$end" "$@" -} - -# yield full macro implementation -function find-macro-implementation-decl() { - test $# -ge 2 - local what end - # only unindented defines, only whole-word match - what="/^#define$WB+$1"'([ \t\(]|$)/' - # full implementation, until a line not ending in a backslash. - # Does not handle macros with comments embedded within the definition. - end='/[^\\]$/' - shift - find-decl "$what" "$end" "$@" -} - -# yield all first lines of $1 macro invocations, -# heuristic for DEFINE_GUARD()-like macros -function find-macro-invocation-decl() { - test $# -ge 2 - local what end - # only unindented defines, only whole-word match, with opening brace - # on the first line - what="/^${1}$WB*\(/" - end=1 # only first line - shift - find-decl "$what" "$end" "$@" -} - -# yield first line of $1 typedef definition -# This only handles typedefs where the name is on first line -function find-typedef-decl() { - test $# -ge 2 - local what end - # Assumes type name is followed by other ')', '(', or ';', or - # whitespace - what="/^typedef$WB.*$1"'[\(\); \t\n]/' - end='/;$/' - shift - find-decl "$what" "$end" "$@" -} - -# yield symbol line from Module.symvers -function find-symbol-decl() { - test $# -ge 2 - local what end - what="/^0x[0-9a-f]+\t$1\t/" - end=1 # only one line - shift - find-decl "$what" "$end" "$@" -} - -# gen() - DSL-like function to wrap around all the other -# -# syntax: -# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in -# gen DEFINE if string "actual" equals "expected" - -# where: -# DEFINE is HAVE_ or NEED_ #define to print; -# `if` is there to just read it easier and made syntax easier to check; -# -# NAME is the name for what we are looking for; -# -# `if string` can be used to check if a provided string matches an expected -# value. The define will only be generated if the strings are exactly -# equal. Otherwise, the define will not be generated. When operating in -# UNIFDEF_MODE, -DDEFINE is output when the strings are equal, while -# -UDEFINE is output when the strings are not equal. This is intended -# for cases where a more complex conditional is required, such as -# generating a define when multiple different functions exist. -# -# Ex: -# -# FUNC1="$(find-fun-decl devlink_foo1 devlink.h)" -# FUNC2="$(find-fun-decl devlink_foo2 devlink.h)" -# gen HAVE_FOO_12 if string "${FUNC1:+1}${FUNC2:+1}" equals "11" -# -# KIND specifies what kind of declaration/definition we are looking for, -# could be: fun, enum, struct, method, macro, typedef, symbol, -# 'anonymous enum', or 'implementation of macro' -# for KIND=method, we are looking for function ptr named METHOD in struct -# named NAME (two optional args are then necessary (METHOD & of)); -# -# for KIND=symbol, we are looking for a symbol definition in the format of -# Module.symvers. To verify that the symbol is exported by a particular -# module, the matches syntax can be used. -# -# for KIND='anonymous enum' we are looking for all anonymous enum -# definitions (i.e. an enum without a name). This is usually combined with -# "matches" or "lacks" to check for a specific value in any anonymous enum -# within the files. Unlike other KINDs, 'anonymous enum' syntax does not -# include NAME. -# -# for KIND='implementation of macro' we are looking for the full -# implementation of the macro, not just its first line. This is usually -# combined with "matches" or "lacks". -# -# next [optional] args could be used: -# matches PATTERN - use to grep for the PATTERN within definition -# (eg, for ext_ack param) -# lacks - use to add #define only if there is no match of the PATTERN, -# *but* the NAME is *found* -# absent - the NAME that we grep for must be not found -# (ie: function not exisiting) -# -# without this optional params, behavior is the same as with -# `matches .` - use to grep just for existence of NAME; -# -# `in` is there to ease syntax, similar to `if` before. -# -# is just space-separate list of files to look in, -# single (-) for stdin. -# -# PATTERN is an awk pattern, will be wrapped by two slashes (/) -# -# The usual output is a list of "#define " lines for each flag that has -# a matched definition. When UNIFDEF_MODE is set to a non-zero string, the -# output is instead a sequence of "-D" for each matched definition, and -# "-U" for each definition which didn't match. -function gen() { - test $# -ge 4 || die 20 "too few arguments, $# given, at least 4 needed" - local define if_kw kind name in_kw # mandatory - local of_kw method_name operator pattern # optional - local src_line="${BASH_SOURCE[0]}:${BASH_LINENO[0]}" - define="$1" - if_kw="$2" - kind="$3" - local orig_args_cnt=$# - shift 3 - [ "$if_kw" != if ] && die 21 "$src_line: 'if' keyword expected, '$if_kw' given" - case "$kind" in - string) - local actual_str expect_str equals_kw missing_fmt found_fmt - - test $# -ge 3 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 6 needed" - - actual_str="$1" - equals_kw="$2" - expect_str="$3" - shift 3 - - if [ -z ${UNIFDEF_MODE:+1} ]; then - found_fmt="#define %s 1\n" - missing_fmt="" - else - found_fmt="-D%s\n" - missing_fmt="-U%s\n" - fi - - if [ "${actual_str}" = "${expect_str}" ]; then - printf -- "$found_fmt" "$define" - else - printf -- "$missing_fmt" "$define" - fi - - return - ;; - anonymous) - test $# -ge 3 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 6 needed" - anon_kind="$1" - name="" - shift - # Other anonymous matches may be added in the future. - [ "$anon_kind" != enum ] && die 31 "$src_line: anonymous checks do not work with '$anon_kind'" - kind="anon-$anon_kind" - ;; - fun|enum|struct|macro|typedef|symbol) - test $# -ge 3 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 6 needed" - name="$1" - shift - ;; - method) - test $# -ge 5 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed" - method_name="$1" - of_kw="$2" - name="$3" - shift 3 - [ "$of_kw" != of ] && die 23 "$src_line: 'of' keyword expected, '$of_kw' given" - ;; - implementation) - test $# -ge 5 || die 28 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed" - of_kw="$1" - kind="$2" - name="$3" - shift 3 - [ "$of_kw" != of ] && die 29 "$src_line: 'of' keyword expected, '$of_kw' given" - [ "$kind" != macro ] && die 30 "$src_line: implementation only supports 'macro', '$kind' given" - kind=macro-implementation - ;; - invocation) - test $# -ge 5 || die 32 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed" - of_kw="$1" - kind="$2" - name="$3" - shift 3 - [ "$of_kw" != of ] && die 33 "$src_line: 'of' keyword expected, '$of_kw' given" - [ "$kind" != macro ] && die 34 "$src_line: invocation only supports 'macro', '$kind' given" - kind=macro-invocation - ;; - *) die 24 "$src_line: unknown KIND ($kind) to look for" ;; - esac - operator="$1" - case "$operator" in - absent) - local next_kw next_op - next_kw="$2" - in_kw="$next_kw" - next_op="$3" - if [[ "$next_kw" = or && "$next_op" = lacks ]]; then - # intentionally keeping $operator as 'absent'... - # but setting 'pattern' to something (not just '.') - shift 3 - test $# -ge 3 || die 39 "$src_line: too few parameters following 'absent or lacks' operator composition, pattern, 'in' keyword and filename needed" - pattern="$1" - in_kw="$2" - else - pattern='.' - fi - shift 2 - ;; - matches|lacks) - pattern="$2" - in_kw="$3" - shift 3 - ;; - in) - operator=matches - pattern='.' - in_kw=in - shift - ;; - *) die 25 "$src_line: unknown OPERATOR ($operator) to look for" ;; - esac - [ "$in_kw" != in ] && die 26 "$src_line: 'in' keyword expected, '$in_kw' given" - test $# -ge 1 || die 27 "$src_line: too few arguments, at least one filename expected" - - local first_decl= - if [ "$kind" = method ]; then - first_decl="$(find-struct-decl "$name" "$@")" || exit 40 - # prepare params for next lookup phase - set -- - # overwrite $@ to be single dash (-) - name="$method_name" - kind=fun - elif [[ $# = 1 && "$1" = '-' ]]; then - # avoid losing stdin provided to gen() due to redirection (<<<) - first_decl="$(cat -)" - fi - - local unifdef - unifdef=${UNIFDEF_MODE:+1} - - # lookup the NAME - local body - body="$(find-$kind-decl "$name" "$@" <<< "$first_decl")" || exit 41 - awk -v define="$define" -v pattern="$pattern" -v "$operator"=1 -v unifdef="$unifdef" ' - BEGIN { - # prepend "identifier boundary" to pattern, also append - # it, but only for patterns not ending with such already - # - # eg: "foo" -> "\bfoo\b" - # "struct foo *" -> "\bstruct foo *" - - # Note that mawk does not support "\b", so we have our - # own approximation, NI - NI = "[^A-Za-z0-9_]" # "Not an Indentifier" - - if (!match(pattern, NI "$")) - pattern = pattern "(" NI "|$)" - pattern = "(^|" NI ")" pattern - } - /./ { not_empty = 1 } - $0 ~ pattern { found = 1 } - END { - if (unifdef) { - found_fmt="-D%s\n" - missing_fmt="-U%s\n" - } else { - found_fmt="#define %s 1\n" - missing_fmt="" - } - - if (lacks && !found && not_empty || matches && found || absent && !found) - printf(found_fmt, define) - else if (missing_fmt) - printf(missing_fmt, define) - } - ' <<< "$body" -} - -# check() - Like gen, but return true/false instead of generating output -# -# syntax: -# See gen(), except do not pass a DEFINE name, or the action keyword. -function check() { - # Always run check in unifdef mode - local UNIFDEF_MODE=1 - - [[ "$(gen CHECK if "$@")" = "-DCHECK" ]] -} - -# tell if given flag is enabled in .config -# return 0 if given flag is enabled, 1 otherwise -# inputs: -# $1 - flag to check (whole word, without _MODULE suffix) -# env flag $CONFIG_FILE -# -# there are two "config" formats supported, to ease up integrators lifes -# .config (without leading #~ prefix): -#~ # CONFIG_ACPI_EC_DEBUGFS is not set -#~ CONFIG_ACPI_AC=y -#~ CONFIG_ACPI_VIDEO=m -# and autoconf.h, which would be: -#~ #define CONFIG_ACPI_AC 1 -#~ #define CONFIG_ACPI_VIDEO_MODULE 1 -function config_has() { - grep -qE "^(#define )?$1((_MODULE)? 1|=m|=y)$" "$CONFIG_FILE" -} - -# try to locate a suitable config file from KOBJ -# -# On success, the CONFIG_FILE variable will be updated to reflect the full -# path to a configuration file. -# -# Depends on KSRC being set -function find_config_file() { - local -a CSP - local file - local diagmsgs=/dev/stderr - - [ -n "${QUIET_COMPAT-}" ] && diagmsgs=/dev/null - - if ! [ -d "${KSRC-}" ]; then - return - fi - - CSP=( - "$KOBJ/include/generated/autoconf.h" - "$KOBJ/include/linux/autoconf.h" - "$KOBJ/.config" - ) - - for file in "${CSP[@]}"; do - if [ -f $file ]; then - echo >&"$diagmsgs" "using CONFIG_FILE=$file" - CONFIG_FILE=$file - return - fi - done -} diff --git a/kcompat_defs.h b/kcompat_defs.h deleted file mode 100644 index 606caae..0000000 --- a/kcompat_defs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (C) 2019-2025 Intel Corporation */ - -#ifndef _KCOMPAT_DEFS_H_ -#define _KCOMPAT_DEFS_H_ - -#ifndef LINUX_VERSION_CODE -#include -#else -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif -#endif /* LINUX_VERSION_CODE */ - -#ifndef UTS_RELEASE -#include -#endif - -/* - * Include the definitions file for HAVE/NEED flags for the standard upstream - * kernels. - * - * Then, based on the distribution we detect, load the distribution specific - * definitions file that customizes the definitions for the target - * distribution. - */ -#include "kcompat_std_defs.h" - -#ifdef CONFIG_SUSE_KERNEL -#include "kcompat_sles_defs.h" -#elif UBUNTU_VERSION_CODE -#include "kcompat_ubuntu_defs.h" -#elif RHEL_RELEASE_CODE -#include "kcompat_rhel_defs.h" -#endif -#endif /* _KCOMPAT_DEFS_H_ */ diff --git a/kcompat_rhel_defs.h b/kcompat_rhel_defs.h deleted file mode 100644 index 5434f51..0000000 --- a/kcompat_rhel_defs.h +++ /dev/null @@ -1,138 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (C) 2019-2025 Intel Corporation */ - -#ifndef _KCOMPAT_RHEL_DEFS_H_ -#define _KCOMPAT_RHEL_DEFS_H_ - -/* This is the RedHat Enterprise Linux distribution specific definitions file. - * It defines what features need backports for a given version of the RHEL - * kernel. - * - * It checks the RHEL_RELEASE_CODE and RHEL_RELEASE_VERSION macros to decide - * what support the target kernel has. - * - * It assumes that kcompat_std_defs.h has already been processed, and will - * #define or #undef any flags that have changed based on backports done by - * RHEL. - */ - -#if !RHEL_RELEASE_CODE -#error "RHEL_RELEASE_CODE is 0 or undefined" -#endif - -#ifndef RHEL_RELEASE_VERSION -#error "RHEL_RELEASE_VERSION is undefined" -#endif - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3)) -#define NEED_NETDEV_TXQ_BQL_PREFETCH -#else /* >= 7.3 */ -#endif /* 7.3 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,4)) -#define NEED_BUILD_BUG_ON -#else /* >= 7.4 */ -#define HAVE_RHEL7_EXTENDED_OFFLOAD_STATS -#endif /* 7.4 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,5)) -#else /* >= 7.5 */ -#define HAVE_FLOW_DISSECTOR_KEY_IP -#endif /* 7.5 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,6)) -#undef HAVE_XDP_BUFF_RXQ -#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS -#else /* >= 7.6 */ -#undef NEED_JIFFIES_64_TIME_IS_MACROS -#undef NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0 -#undef NEED_TC_SETUP_QDISC_MQPRIO -#endif /* 7.6 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,7)) -#else /* >= 7.7 */ -#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR -#define HAVE_ETHTOOL_NEW_100G_BITS -#undef NEED_IN_TASK -#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP -#endif /* 7.7 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0)) -#else /* >= 8.0 */ -#undef HAVE_ETHTOOL_NEW_100G_BITS -#define HAVE_NDO_OFFLOAD_STATS -#undef HAVE_RHEL7_EXTENDED_OFFLOAD_STATS -#endif /* 8.0 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,1)) -#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE -#else /* >= 8.1 */ -#define HAVE_ETHTOOL_NEW_100G_BITS -#undef NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE -#undef NEED_INDIRECT_CALL_WRAPPER_MACROS -#define HAVE_INDIRECT_CALL_WRAPPER_HEADER -#endif /* 8.1 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,2)) -#else /* >= 8.2 */ -#undef NEED_FLOW_INDR_BLOCK_CB_REGISTER -#define HAVE_FLOW_INDR_BLOCK_LOCK -#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID -#define HAVE_NETDEV_SB_DEV -#endif /* 8.2 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,3)) -#else /* >= 8.3 */ -#undef NEED_CPU_LATENCY_QOS_RENAME -#define HAVE_RT_IRQ_SCHED_FIX -#endif /* 8.3 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,4)) -#else /* >= 8.4 */ -#undef NEED_DEVLINK_PORT_ATTRS_SET_STRUCT -#undef HAVE_XDP_QUERY_PROG -#define HAVE_AF_XDP_ZC_SUPPORT -#define HAVE_MEM_TYPE_XSK_BUFF_POOL -#define HAVE_NDO_XSK_WAKEUP -#define XSK_UMEM_RETURNS_XDP_DESC -#undef NEED_XSK_UMEM_GET_RX_FRAME_SIZE -#define HAVE_ETHTOOL_COALESCE_PARAMS_SUPPORT -#endif /* 8.4 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,5)) -#else /* >= 8.5 */ -#undef HAVE_NAPI_BUSY_LOOP -#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS -#define NO_XDP_QUERY_XSK_UMEM -#undef NEED_XSK_BUFF_POOL_RENAME -#define HAVE_NETDEV_BPF_XSK_POOL -#define HAVE_AF_XDP_NETDEV_UMEM -#define HAVE_DEVLINK_OPS_CREATE_DEL -#endif /* 8.5 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,7)) -#else /* >= 8.7 */ -#undef NEED_DEVLINK_ALLOC_SETS_DEV -#define HAVE_DEVLINK_SET_STATE_3_PARAM -#endif /* 8.7 */ - -/*****************************************************************************/ -#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9,0)) -#else /* >= 9.0 */ -#define HAVE_XDP_BUFF_RXQ -#endif /* 9.0 */ - -/*****************************************************************************/ -#endif /* _KCOMPAT_RHEL_DEFS_H_ */ diff --git a/kcompat_std_defs.h b/kcompat_std_defs.h deleted file mode 100644 index 9eae7b0..0000000 --- a/kcompat_std_defs.h +++ /dev/null @@ -1,220 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (C) 2019-2025 Intel Corporation */ - -#ifndef _KCOMPAT_STD_DEFS_H_ -#define _KCOMPAT_STD_DEFS_H_ - -/* This file contains the definitions for what kernel features need backports - * for a given kernel. It targets only the standard stable kernel releases. - * It must check only LINUX_VERSION_CODE and assume the kernel is a standard - * release, and not a custom distribution. - * - * It must define HAVE_ and NEED_ for features. It must not - * implement any backports, instead leaving the implementation to the - * kcompat_impl.h header. - * - * If a feature can be easily implemented as a replacement macro or fully - * backported, use a NEED_ to indicate that the feature needs - * a backport. (If NEED_ is undefined, then no backport for that feature - * is needed). - * - * If a feature cannot be easily implemented in kcompat directly, but - * requires drivers to make specific changes such as stripping out an entire - * feature or modifying a function pointer prototype, use a HAVE_. - */ - -#ifndef LINUX_VERSION_CODE -#error "LINUX_VERSION_CODE is undefined" -#endif - -#ifndef KERNEL_VERSION -#error "KERNEL_VERSION is undefined" -#endif - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)) -#else /* >= 4,8,0 */ -#define HAVE_PCI_ALLOC_IRQ -#endif /* 4,8,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)) -#define NEED_JIFFIES_64_TIME_IS_MACROS -#else /* >= 4,9,0 */ -#define HAVE_KTHREAD_DELAYED_API -#define HAVE_NDO_OFFLOAD_STATS -#endif /* 4,9,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,62)) -#define NEED_IN_TASK -#else /* >= 4,9,62 */ -#endif /* 4,9,62 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)) -#else /* >= 4,12,0 */ -#define HAVE_NAPI_BUSY_LOOP -#endif /* 4,12,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0)) -#else /* >= 4,13,0 */ -#define HAVE_FLOW_DISSECTOR_KEY_IP -#endif /* 4,13,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) -#define NEED_TC_SETUP_QDISC_MQPRIO -#define NEED_NETDEV_XDP_STRUCT -#else /* >= 4,15,0 */ -#define HAVE_NDO_BPF -#endif /* 4,15,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0)) -#define NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0 -#else /* >= 4,16,0 */ -#define HAVE_XDP_BUFF_RXQ -#define HAVE_XDP_RXQ_INFO_REG_3_PARAMS -#endif /* 4,16,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,17,0)) -#define NEED_CONVERT_ART_NS_TO_TSC -#else /* >= 4,17,0 */ -#endif /* 4,17,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0)) -#define NEED_MACVLAN_ACCEL_PRIV -#define NEED_MACVLAN_RELEASE_L2FW_OFFLOAD -#define NEED_MACVLAN_SUPPORTS_DEST_FILTER -#else /* >= 4,18,0 */ -#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR -#endif /* 4,18,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)) -#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE -#else /* >= 4,19,0 */ -#define HAVE_TC_ETF_QOPT_OFFLOAD -#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP -#endif /* 4,19,0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)) -#define NEED_INDIRECT_CALL_WRAPPER_MACROS -#else /* >= 5.0.0 */ -#define HAVE_INDIRECT_CALL_WRAPPER_HEADER -#endif /* 5.0.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)) -#else /* >= 5.1.0 */ -#define HAVE_ETHTOOL_200G_BITS -#define HAVE_ETHTOOL_NEW_100G_BITS -#endif /* 5.1.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)) -#else /* >= 5.2.0 */ -#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID -#endif /* 5.2.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)) -#define NEED_FLOW_INDR_BLOCK_CB_REGISTER -#else /* >= 5.4.0 */ -#define HAVE_FLOW_INDR_BLOCK_LOCK -#define HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT -#endif /* 5.4.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0)) -#define NEED_CPU_LATENCY_QOS_RENAME -#else /* >= 5.7.0 */ -#endif /* 5.7.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)) -#define NEED_XSK_UMEM_GET_RX_FRAME_SIZE -#else /* >= 5.8.0 */ -#undef HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT -#define HAVE_RT_IRQ_SCHED_FIX -#endif /* 5.8.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0)) -#define NEED_DEVLINK_PORT_ATTRS_SET_STRUCT -#define HAVE_XDP_QUERY_PROG -#define NEED_INDIRECT_CALL_3_AND_4 -#else /* >= 5.9.0 */ -#define HAVE_TASKLET_SETUP -#endif /* 5.9.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)) -#define NEED_XSK_BUFF_POOL_RENAME -#else /* >= 5.10.0 */ -#define HAVE_UDP_TUNNEL_NIC_SHARED -#define HAVE_NETDEV_BPF_XSK_POOL -#endif /* 5.10.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)) -#else /* >= 5.11.0 */ -#define HAVE_XSK_BATCHED_DESCRIPTOR_INTERFACES -#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS -#define HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS -#endif /* 5.11.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)) -#define NEED_EXPORT_INDIRECT_CALLABLE -#else /* >= 5.12.0 */ -#define HAVE_DEVLINK_OPS_CREATE_DEL -#endif /* 5.12.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0)) -#else /* >= 5.13.0 */ -#define HAVE_XPS_MAP_TYPE -#endif /* 5.13.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,14,0)) -#else /* >= 5.14.0 */ -#define HAVE_TTY_WRITE_ROOM_UINT -#endif /* 5.14.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0)) -#define NEED_DEVLINK_ALLOC_SETS_DEV -#else /* >= 5.15.0 */ -#define HAVE_DEVICE_IN_MDEV_PARENT_OPS -#define NEED_PCI_IOV_VF_ID -#define HAVE_DEVLINK_SET_STATE_3_PARAM -#endif /* 5.15.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,16,0)) -#else /* >= 5.16.0 */ -#define HAVE_XSK_BATCHED_RX_ALLOC -#endif /* 5.16.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) -#else /* >=5.18.0*/ -#undef NEED_PCI_IOV_VF_ID -#undef HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS -#endif /* 5.18.0 */ - -/*****************************************************************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0)) -#else /* >=6.1.0 */ -#define HAVE_FLOW_DISSECTOR_KEY_L2TPV3 -#define HAVE_TTY_TERMIOS_CONST_STRUCT -#endif /* 6.1.0 */ - -#endif /* _KCOMPAT_STD_DEFS_H_ */