#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright(c) 2019, Intel Corp. All rights reserved.

# Global variables
export SIZE_1=1
export SIZE_512=512
export SIZE_1K=1024
export SIZE_4K=4096
export SIZE_64K=65536
export SIZE_1M=1048576
export SIZE_2M=2097152
export EXIT_FAILURE=1
export EXIT_SKIP=77
TESTDIR=/usr/libexec/accel-config/test
BINDIR=/usr/bin

# ACCFG
#
if [ -f "../accfg/accel-config" ] && [ -x "../accfg/accel-config" ]; then
	export ACCFG=../accfg/accel-config
elif [ -f "./accfg/accel-config" ] && [ -x "./accfg/accel-config" ]; then
	export ACCFG=./accfg/accel-config
elif [ -f "$BINDIR/accel-config" ] && [ -x "$BINDIR/accel-config" ]; then
	export ACCFG="$BINDIR"/accel-config
else
	echo "Couldn't find an accel-config binary"
	exit "$EXIT_FAILURE"
fi

# DSATEST
#
if [ -f "./dsa_test" ] && [ -x "./dsa_test" ]; then
	export DSATEST=./dsa_test
elif [ -f "$TESTDIR/dsa_test" ] && [ -x "$TESTDIR/dsa_test" ]; then
	export DSATEST="$TESTDIR"/dsa_test
else
	echo "Couldn't find an dsa_test binary"
	exit "$EXIT_FAILURE"
fi

# IAATEST
#
if [ -f "./iaa_test" ] && [ -x "./iaa_test" ]; then
	export IAATEST=./iaa_test
elif [ -f "$TESTDIR/iaa_test" ] && [ -x "$TESTDIR/iaa_test" ]; then
	export IAATEST="$TESTDIR"/iaa_test
else
	echo "Couldn't find an iaa_test binary"
	exit "$EXIT_FAILURE"
fi

# CONFIGS
#
if [ -f "./configs/2g2q_user_1.conf" ]; then
	export CONFIG1=./configs/2g2q_user_1.conf
elif [ -f "$TESTDIR/configs/2g2q_user_1.conf" ]; then
	export CONFIG1="$TESTDIR"/configs/2g2q_user_1.conf
else
	echo "Can't find config 1 file"
	exit "$EXIT_FAILURE"
fi

# CONFIGS
#
if [ -f "./configs/2g2q_user_2.conf" ]; then
    export CONFIG2=./configs/2g2q_user_2.conf
elif [ -f "$TESTDIR/configs/2g2q_user_2.conf" ]; then
    export CONFIG2="$TESTDIR"/configs/2g2q_user_2.conf
else
    echo "Can't find config 2 file"
    exit "$EXIT_FAILURE"
fi

# Functions

# err
# $1: line number which error detected
# $2: cleanup function (optional)
#
err()
{
	echo test/"$(basename "$0")": failed at line "$1"
	[ -n "$2" ] && "$2"
	# shellcheck disable=SC2154
	exit "$rc"
}

# check_min_kver
# $1: Supported kernel version. format: X.Y
#
check_min_kver()
{
	local ver="$1"
	: "${KVER:=$(uname -r)}"

	[ -n "$ver" ] || return 1
	[[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
}

# do_skip
# $1: Skip message
#
do_skip()
{
	echo kernel "$(uname -r)": "$1"
	exit "$EXIT_SKIP"
}

# check_prereq
# $1: command to check
#
check_prereq()
{
	if ! command -v "$1" >/dev/null; then
		do_skip "missing $1, skipping..."
	fi
}

# Disable all active devices dsa/iax and enabled wqs.
# Use accel-config tool to disable the device and wq.
disable_all() {
  for device_type in 'dsa' 'iax'; do
    # Kernel before 5.13 has dsa and iax bus. Because of ABI change, iax
    # bus is removed. All devices are in /sys/bus/dsa/devices.
    if [ -d /sys/bus/iax ] && [ $device_type == 'iax' ]; then
      DSA_DEVICE_PATH="/sys/bus/iax/devices"
    else
      DSA_DEVICE_PATH="/sys/bus/dsa/devices"
    fi

    if ! ls "${DSA_DEVICE_PATH}/" | grep -qE "${device_type}[0-9]*"; then
	continue
    fi

    # Get available devices
    for device_path in ${DSA_DEVICE_PATH}/${device_type}* ; do
      [[ $(echo "$device_path" | grep -c '!') -eq 0 ]] && {
		# Get wqs and disable it if the status is enabled
        for wqp in ${device_path}/wq* ; do
          [[ $( cat "${wqp}"/state ) == "enabled" ]] && {
            wq=${wqp##${DSA_DEVICE_PATH}/}
            accel-config disable-wq "${wq}"
            echo "-1" > "${wqp}"/group_id
          }
          done
		# Disable device
        [[ $( cat "${device_path}"/state ) == "enabled" ]] && {
          accel-config disable-device "${device_path##${DSA_DEVICE_PATH}/}"
        }
		# Remove group id of engine
        for engine in ${device_path}/engine* ; do
          echo -1 > "$engine"/group_id
        done
      }
    done
  done
}

# cleanup
#
_cleanup()
{
  # iaa_crypto will enable iax devices by default after kernel 6.6,
  # need to disable all enabled devices before unloading the module.
	disable_all

	lsmod | grep -wq idxd_vdev && {
		rmmod idxd_vdev
	}
	lsmod | grep -wq idxd_uacce && {
		rmmod idxd_uacce
	}
	lsmod | grep -wq iaa_crypto && {
		rmmod iaa_crypto
	}
	lsmod | grep -wq iax_crypto && {
		rmmod iax_crypto
	}
	lsmod | grep -wq idxd && {
		rmmod idxd
	}
	lsmod | grep -wq vfio_pci && {
		rmmod vfio_pci
	}
	sleep 1
	modprobe idxd
	sleep 1
	modprobe vfio_pci

	disable_all
	lsmod | grep -wq iaa_crypto && {
		rmmod iaa_crypto
	}
	return 0
}

# json2var
# stdin: json
#
json2var()
{
	sed -e "s/[{}\",]//g; s/\[//g; s/\]//g; s/:/=/g"
}

# translate opcode to name
# $1 opcode
#
opcode2name()
{
	local opcode="$1"
	dec_opcode=$((opcode))
	case $dec_opcode in
	"0")
		echo "NOOP"
		;;
	"2")
		echo "DRAIN"
		;;
	"3")
		echo "MEMMOVE"
		;;
	"4")
		echo "MEMFILL"
		;;
	"5")
		echo "COMPARE"
		;;
	"6")
		echo "COMPVAL"
		;;
	"7")
		echo "CR_DELTA"
		;;
	"8")
		echo "AP_DELTA"
		;;
	"9")
		echo "DUALCAST"
		;;
	"16")
		echo "CRCGEN"
		;;
	"17")
		echo "COPY_CRC"
		;;
	"18")
		echo "DIF_CHECK"
		;;
	"19")
		echo "DIF_INS"
		;;
	"20")
		echo "DIF_STRP"
		;;
	"21")
		echo "DIF_UPDT"
		;;
	"32")
		echo "CFLUSH"
		;;
	*)
		echo "UNKNOWN"
		;;
	esac
}

# translate WQ mode code to name
# $1 Wq mode code
#
wq_mode2name()
{
	local wq_mode="$1"
	dec_wq_mode=$((wq_mode))
	case $dec_wq_mode in
	"0")
		echo "dedicated"
		;;
	"1")
		echo "shared"
		;;
	*)
		echo "UNKNOWN"
		;;
	esac
}
