18c2ecf20Sopenharmony_ci#!/bin/bash
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ciSYSFS=
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci# Kselftest framework requirement - SKIP code is 4.
78c2ecf20Sopenharmony_ciksft_skip=4
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciprerequisite()
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	msg="skip all tests:"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	if [ $UID != 0 ]; then
148c2ecf20Sopenharmony_ci		echo $msg must be run as root >&2
158c2ecf20Sopenharmony_ci		exit $ksft_skip
168c2ecf20Sopenharmony_ci	fi
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	if [ ! -d "$SYSFS" ]; then
218c2ecf20Sopenharmony_ci		echo $msg sysfs is not mounted >&2
228c2ecf20Sopenharmony_ci		exit $ksft_skip
238c2ecf20Sopenharmony_ci	fi
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then
268c2ecf20Sopenharmony_ci		echo $msg memory hotplug is not supported >&2
278c2ecf20Sopenharmony_ci		exit $ksft_skip
288c2ecf20Sopenharmony_ci	fi
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if ! grep -q 1 $SYSFS/devices/system/memory/memory*/removable; then
318c2ecf20Sopenharmony_ci		echo $msg no hot-pluggable memory >&2
328c2ecf20Sopenharmony_ci		exit $ksft_skip
338c2ecf20Sopenharmony_ci	fi
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#
378c2ecf20Sopenharmony_ci# list all hot-pluggable memory
388c2ecf20Sopenharmony_ci#
398c2ecf20Sopenharmony_cihotpluggable_memory()
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	local state=${1:-.\*}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	for memory in $SYSFS/devices/system/memory/memory*; do
448c2ecf20Sopenharmony_ci		if grep -q 1 $memory/removable &&
458c2ecf20Sopenharmony_ci		   grep -q $state $memory/state; then
468c2ecf20Sopenharmony_ci			echo ${memory##/*/memory}
478c2ecf20Sopenharmony_ci		fi
488c2ecf20Sopenharmony_ci	done
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cihotpluggable_offline_memory()
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	hotpluggable_memory offline
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cihotpluggable_online_memory()
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	hotpluggable_memory online
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cimemory_is_online()
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	grep -q online $SYSFS/devices/system/memory/memory$1/state
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cimemory_is_offline()
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	grep -q offline $SYSFS/devices/system/memory/memory$1/state
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cionline_memory()
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	echo online > $SYSFS/devices/system/memory/memory$1/state
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cioffline_memory()
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	echo offline > $SYSFS/devices/system/memory/memory$1/state
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cionline_memory_expect_success()
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	local memory=$1
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if ! online_memory $memory; then
868c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected fail >&2
878c2ecf20Sopenharmony_ci		return 1
888c2ecf20Sopenharmony_ci	elif ! memory_is_online $memory; then
898c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected offline >&2
908c2ecf20Sopenharmony_ci		return 1
918c2ecf20Sopenharmony_ci	fi
928c2ecf20Sopenharmony_ci	return 0
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cionline_memory_expect_fail()
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	local memory=$1
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	if online_memory $memory 2> /dev/null; then
1008c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected success >&2
1018c2ecf20Sopenharmony_ci		return 1
1028c2ecf20Sopenharmony_ci	elif ! memory_is_offline $memory; then
1038c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected online >&2
1048c2ecf20Sopenharmony_ci		return 1
1058c2ecf20Sopenharmony_ci	fi
1068c2ecf20Sopenharmony_ci	return 0
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cioffline_memory_expect_success()
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	local memory=$1
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	if ! offline_memory $memory; then
1148c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected fail >&2
1158c2ecf20Sopenharmony_ci		return 1
1168c2ecf20Sopenharmony_ci	elif ! memory_is_offline $memory; then
1178c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected offline >&2
1188c2ecf20Sopenharmony_ci		return 1
1198c2ecf20Sopenharmony_ci	fi
1208c2ecf20Sopenharmony_ci	return 0
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cioffline_memory_expect_fail()
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	local memory=$1
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if offline_memory $memory 2> /dev/null; then
1288c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected success >&2
1298c2ecf20Sopenharmony_ci		return 1
1308c2ecf20Sopenharmony_ci	elif ! memory_is_online $memory; then
1318c2ecf20Sopenharmony_ci		echo $FUNCNAME $memory: unexpected offline >&2
1328c2ecf20Sopenharmony_ci		return 1
1338c2ecf20Sopenharmony_ci	fi
1348c2ecf20Sopenharmony_ci	return 0
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cierror=-12
1388c2ecf20Sopenharmony_cipriority=0
1398c2ecf20Sopenharmony_ci# Run with default of ratio=2 for Kselftest run
1408c2ecf20Sopenharmony_ciratio=2
1418c2ecf20Sopenharmony_ciretval=0
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ciwhile getopts e:hp:r: opt; do
1448c2ecf20Sopenharmony_ci	case $opt in
1458c2ecf20Sopenharmony_ci	e)
1468c2ecf20Sopenharmony_ci		error=$OPTARG
1478c2ecf20Sopenharmony_ci		;;
1488c2ecf20Sopenharmony_ci	h)
1498c2ecf20Sopenharmony_ci		echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]"
1508c2ecf20Sopenharmony_ci		exit
1518c2ecf20Sopenharmony_ci		;;
1528c2ecf20Sopenharmony_ci	p)
1538c2ecf20Sopenharmony_ci		priority=$OPTARG
1548c2ecf20Sopenharmony_ci		;;
1558c2ecf20Sopenharmony_ci	r)
1568c2ecf20Sopenharmony_ci		ratio=$OPTARG
1578c2ecf20Sopenharmony_ci		if [ "$ratio" -gt 100 ] || [ "$ratio" -lt 0 ]; then
1588c2ecf20Sopenharmony_ci			echo "The percentage should be an integer within 0~100 range"
1598c2ecf20Sopenharmony_ci			exit 1
1608c2ecf20Sopenharmony_ci		fi
1618c2ecf20Sopenharmony_ci		;;
1628c2ecf20Sopenharmony_ci	esac
1638c2ecf20Sopenharmony_cidone
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciif ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
1668c2ecf20Sopenharmony_ci	echo "error code must be -4095 <= errno < 0" >&2
1678c2ecf20Sopenharmony_ci	exit 1
1688c2ecf20Sopenharmony_cifi
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ciprerequisite
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ciecho "Test scope: $ratio% hotplug memory"
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci#
1758c2ecf20Sopenharmony_ci# Online all hot-pluggable memory
1768c2ecf20Sopenharmony_ci#
1778c2ecf20Sopenharmony_cihotpluggable_num=`hotpluggable_offline_memory | wc -l`
1788c2ecf20Sopenharmony_ciecho -e "\t online all hot-pluggable memory in offline state:"
1798c2ecf20Sopenharmony_ciif [ "$hotpluggable_num" -gt 0 ]; then
1808c2ecf20Sopenharmony_ci	for memory in `hotpluggable_offline_memory`; do
1818c2ecf20Sopenharmony_ci		echo "offline->online memory$memory"
1828c2ecf20Sopenharmony_ci		if ! online_memory_expect_success $memory; then
1838c2ecf20Sopenharmony_ci			retval=1
1848c2ecf20Sopenharmony_ci		fi
1858c2ecf20Sopenharmony_ci	done
1868c2ecf20Sopenharmony_cielse
1878c2ecf20Sopenharmony_ci	echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
1888c2ecf20Sopenharmony_cifi
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci#
1918c2ecf20Sopenharmony_ci# Offline $ratio percent of hot-pluggable memory
1928c2ecf20Sopenharmony_ci#
1938c2ecf20Sopenharmony_cihotpluggable_num=`hotpluggable_online_memory | wc -l`
1948c2ecf20Sopenharmony_citarget=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc`
1958c2ecf20Sopenharmony_ciecho -e "\t offline $ratio% hot-pluggable memory in online state"
1968c2ecf20Sopenharmony_ciecho -e "\t trying to offline $target out of $hotpluggable_num memory block(s):"
1978c2ecf20Sopenharmony_cifor memory in `hotpluggable_online_memory`; do
1988c2ecf20Sopenharmony_ci	if [ "$target" -gt 0 ]; then
1998c2ecf20Sopenharmony_ci		echo "online->offline memory$memory"
2008c2ecf20Sopenharmony_ci		if offline_memory_expect_success $memory; then
2018c2ecf20Sopenharmony_ci			target=$(($target - 1))
2028c2ecf20Sopenharmony_ci		fi
2038c2ecf20Sopenharmony_ci	fi
2048c2ecf20Sopenharmony_cidone
2058c2ecf20Sopenharmony_ciif [ "$target" -gt 0 ]; then
2068c2ecf20Sopenharmony_ci	retval=1
2078c2ecf20Sopenharmony_ci	echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?"
2088c2ecf20Sopenharmony_cifi
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci#
2118c2ecf20Sopenharmony_ci# Online all hot-pluggable memory again
2128c2ecf20Sopenharmony_ci#
2138c2ecf20Sopenharmony_cihotpluggable_num=`hotpluggable_offline_memory | wc -l`
2148c2ecf20Sopenharmony_ciecho -e "\t online all hot-pluggable memory in offline state:"
2158c2ecf20Sopenharmony_ciif [ "$hotpluggable_num" -gt 0 ]; then
2168c2ecf20Sopenharmony_ci	for memory in `hotpluggable_offline_memory`; do
2178c2ecf20Sopenharmony_ci		echo "offline->online memory$memory"
2188c2ecf20Sopenharmony_ci		if ! online_memory_expect_success $memory; then
2198c2ecf20Sopenharmony_ci			retval=1
2208c2ecf20Sopenharmony_ci		fi
2218c2ecf20Sopenharmony_ci	done
2228c2ecf20Sopenharmony_cielse
2238c2ecf20Sopenharmony_ci	echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
2248c2ecf20Sopenharmony_cifi
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci#
2278c2ecf20Sopenharmony_ci# Test with memory notifier error injection
2288c2ecf20Sopenharmony_ci#
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ciDEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
2318c2ecf20Sopenharmony_ciNOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ciprerequisite_extra()
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	msg="skip extra tests:"
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/sbin/modprobe -q -r memory-notifier-error-inject
2388c2ecf20Sopenharmony_ci	/sbin/modprobe -q memory-notifier-error-inject priority=$priority
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if [ ! -d "$DEBUGFS" ]; then
2418c2ecf20Sopenharmony_ci		echo $msg debugfs is not mounted >&2
2428c2ecf20Sopenharmony_ci		exit $retval
2438c2ecf20Sopenharmony_ci	fi
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
2468c2ecf20Sopenharmony_ci		echo $msg memory-notifier-error-inject module is not available >&2
2478c2ecf20Sopenharmony_ci		exit $retval
2488c2ecf20Sopenharmony_ci	fi
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ciecho -e "\t Test with memory notifier error injection"
2528c2ecf20Sopenharmony_ciprerequisite_extra
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci#
2558c2ecf20Sopenharmony_ci# Offline $ratio percent of hot-pluggable memory
2568c2ecf20Sopenharmony_ci#
2578c2ecf20Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
2588c2ecf20Sopenharmony_cifor memory in `hotpluggable_online_memory`; do
2598c2ecf20Sopenharmony_ci	if [ $((RANDOM % 100)) -lt $ratio ]; then
2608c2ecf20Sopenharmony_ci		offline_memory_expect_success $memory
2618c2ecf20Sopenharmony_ci	fi
2628c2ecf20Sopenharmony_cidone
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci#
2658c2ecf20Sopenharmony_ci# Test memory hot-add error handling (offline => online)
2668c2ecf20Sopenharmony_ci#
2678c2ecf20Sopenharmony_ciecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
2688c2ecf20Sopenharmony_cifor memory in `hotpluggable_offline_memory`; do
2698c2ecf20Sopenharmony_ci	online_memory_expect_fail $memory
2708c2ecf20Sopenharmony_cidone
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#
2738c2ecf20Sopenharmony_ci# Online all hot-pluggable memory
2748c2ecf20Sopenharmony_ci#
2758c2ecf20Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
2768c2ecf20Sopenharmony_cifor memory in `hotpluggable_offline_memory`; do
2778c2ecf20Sopenharmony_ci	online_memory_expect_success $memory
2788c2ecf20Sopenharmony_cidone
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci#
2818c2ecf20Sopenharmony_ci# Test memory hot-remove error handling (online => offline)
2828c2ecf20Sopenharmony_ci#
2838c2ecf20Sopenharmony_ciecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
2848c2ecf20Sopenharmony_cifor memory in `hotpluggable_online_memory`; do
2858c2ecf20Sopenharmony_ci	offline_memory_expect_fail $memory
2868c2ecf20Sopenharmony_cidone
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
2898c2ecf20Sopenharmony_ci/sbin/modprobe -q -r memory-notifier-error-inject
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ciexit $retval
292