#!/bin/bash # SPDX-License-Identifier: GPL-2.0-only 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 # 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-vdpa() { vh='include/linux/vdpa.h' vm='include/linux/virtio_pci_modern.h' if [ -f $vm ];then gen HAVE_VIRTIO_PCI_MODERN if struct virtio_pci_modern_device in $vm fi #gen HAVE_VDPA_OPS_RESET_INFO if method reset of vdpa_config_ops matches lacks status in "$vh" gen HAVE_VDPA_RESET_LACK_INFO if method reset of vdpa_config_ops lacks state in "$vh" gen HAVE_VDPA_OPS_RESET if method reset of vdpa_config_ops in "$vh" gen HAVE_VDPA_ALLOC_LACK_GROUP if fun __vdpa_alloc_device lacks ngroups in "$vh" gen HAVE_VDPA_ALLOC_LACK_NAME if fun __vdpa_alloc_device lacks name in "$vh" gen HAVE_VDPA_VQ_STATE_LACK_PACKED if struct vdpa_vq_state lacks packed in "$vh" gen HAVE_VDPA_MGMTDEV_OPS if struct vdpa_mgmtdev_ops in "$vh" gen HAVE_VDPA_DEV_SET_CONFIG if struct vdpa_dev_set_config in "$vh" gen HAVE_VDPA_OPS_DEVICE_FEAT if method get_device_features of vdpa_config_ops in "$vh" gen HAVE_VDPA_OPS_GET_CONFIG_SIZE if method get_config_size of vdpa_config_ops in "$vh" gen HAVE_VDPA_OPS_LOG_BASE if method set_log_base of vdpa_config_ops in "$vh" gen HAVE_VDPA_OPS_NUM_MIN if method get_vq_num_min of vdpa_config_ops in "$vh" } function gen-aux() { ah='include/linux/auxiliary_bus.h' mh='include/linux/mod_devicetable.h' if config_has CONFIG_AUXILIARY_BUS; then gen HAVE_AUXILIARY_DRIVER_INT_REMOVE if method remove of auxiliary_driver matches 'int' in "$ah" fi # generate HAVE_AUXILIARY_DEVICE_ID only for cases when it's disabled in .config if ! config_has CONFIG_AUXILIARY_BUS; then gen HAVE_AUXILIARY_DEVICE_ID if struct auxiliary_device_id in "$mh" fi } 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_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_ENABLE_PTM if fun pci_enable_ptm absent in "$pcih" } # all the generations, extracted from main() to keep normal code and various # prep separated function gen-all() { # code above is covered by unit_tests/test_gold.sh if [ -n "${JUST_UNIT_TESTING-}" ]; then return fi gen-aux gen-vdpa gen-pci } function main() { # 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 if [ -d "${KSRC-}" ]; then cd "${KSRC}" fi # 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 # we need some flags from .config or (autoconf.h), required if [ ! -f "${CONFFILE-}" ]; then echo >&2 ".config should be passed as env CONFFILE (and it's not set or not a file)" exit 9 fi echo "#ifndef _KCOMPAT_GENERATED_DEFS_H_" echo "#define _KCOMPAT_GENERATED_DEFS_H_" gen-all echo "#endif /* _KCOMPAT_GENERATED_DEFS_H_ */" 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