#!/bin/dash
# jamesbond 2017
# step 2019

### configuration
INT_PATH=/sys/firmware/acpi/interrupts
DETECT_TIME=5 # seconds
THRESHOLD=10  # shouldn't be more than this, during $DETECT_TIME

### helpers
read_gpe_count() {
	local p count dontcare
	for p in gpe[0-9]*; do
		read count dontcare < $p
		echo $p-$count
	done
}

# $1 - threshold, $2-delay
detect_bad_and_disable() {
	local prev p gpe prevval newval dontcare diff
	local threshold=${1:-$THRESHOLD}
	local detect_time=${2:-$DETECT_TIME}

	echo gpe detecting starts ...
	[ $threshold -le 0 ] && threshold=$THRESHOLD # can't be zero or less
	
	cd $INT_PATH
	prev=$(read_gpe_count)
	sleep $detect_time
	set -- $prev
	for p; do
		gpe=${p%-*}
		prevval=${p#*-}
		read newval dontcare < $gpe
		: $((diff = newval - prevval))
		#echo $gpe $prevval $diff
		if [ $diff -gt $threshold ]; then
			echo $gpe has $diff interrupts, exceeding threshold of $threshold, disabling.
			# step 2019, since k4.10 need "mask" to disable
			# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9c4aa1e
			# https://unix.stackexchange.com/a/528300
			#echo disable > $gpe
			echo mask > $gpe
		fi
	done

	echo gpe detect done
}

### main
[ -d $INT_PATH ] || exit

case $1 in
	--help|-h) echo "Usage: ${0##*/} [threshold] [detect-time]"; exit ;;
	*) detect_bad_and_disable "$1" "$2" ;;
esac
