#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) 2017 Johannes Thumshirn <jthumshirn@suse.de>
#
# Do disable PCI device while doing I/O to it

. tests/block/rc

DESCRIPTION="disable PCI device while doing I/O"
TIMED=1
CAN_BE_ZONED=1

pci_dev_mounted() {
	local d dev p pdev

	pdev="$(_get_pci_dev_from_blkdev)"
	for d in /sys/block/*; do
		dev=${d##*/}
		p=$(_get_pci_from_dev_sysfs "$d")
		[[ $p != "$pdev" ]] && continue
		grep -qe "/dev/$dev" /proc/mounts && return 0
	done
	return 1
}

requires() {
	_have_fio && _have_program setpci
}

device_requires() {
	_require_test_dev_is_pci
	if pci_dev_mounted; then
		SKIP_REASONS+=("mounted block device exists on test target PCI device")
		return 1
	fi
}

test_device() {
	echo "Running ${TEST_NAME}"

	pdev="$(_get_pci_dev_from_blkdev)"

	if _test_dev_is_rotational; then
		size="32m"
	else
		size="1g"
	fi

	# start fio job
	_run_fio_rand_io --filename="$TEST_DEV" --size="$size" \
			--ignore_error=EIO,ENXIO,ENODEV &

	# toggle PCI Command Register's Bus Master Enabling
	while kill -0 $! 2>/dev/null; do
		setpci -s "${pdev}" 4.w=0:4
		sleep .2
		setpci -s "${pdev}" 4.w=4:4
		sleep .2
	done

	echo "Test complete"

	# This test triggers NVME controller resets. When any failure happens
	# during the resets, the driver marks the NVME block devices with zero
	# capacity. Then following tests fail with the zero capacity devices. To
	# get back the correct capacity, remove and rescan the devices.
	if ((!$(<"$TEST_DEV_SYSFS/size"))); then
		echo "$TEST_DEV has zero capacity" >> "$FULL"
		if [[ -w $TEST_DEV_SYSFS/device/device/remove ]] &&
			   [[ -w /sys/bus/pci/rescan ]]; then
			echo "Rescan to tegain the correct capacity" >> "$FULL"
			echo 1 > "$TEST_DEV_SYSFS/device/device/remove"
			echo 1 > /sys/bus/pci/rescan
		fi
	fi
}
