0001
0002
0003
0004 export KSELFTESTS_SKIP=4
0005
0006 log() {
0007 echo >/dev/stderr $*
0008 }
0009
0010 pe_ok() {
0011 local dev="$1"
0012 local path="/sys/bus/pci/devices/$dev/eeh_pe_state"
0013
0014
0015
0016
0017
0018 local eeh_state="$(cat $path 2>/dev/null)"
0019 if [ -z "$eeh_state" ]; then
0020 return 1;
0021 fi
0022
0023 local fw_state="$(echo $eeh_state | cut -d' ' -f1)"
0024 local sw_state="$(echo $eeh_state | cut -d' ' -f2)"
0025
0026
0027
0028 if [ "$((sw_state & 0x3))" -ne 0 ] ; then
0029 return 1
0030 fi
0031
0032
0033
0034
0035
0036 if [ "$((fw_state & 0x18))" -ne "$((0x18))" ] ; then
0037 return 1
0038 fi
0039
0040 return 0;
0041 }
0042
0043 eeh_supported() {
0044 test -e /proc/powerpc/eeh && \
0045 grep -q 'EEH Subsystem is enabled' /proc/powerpc/eeh
0046 }
0047
0048 eeh_test_prep() {
0049 if ! eeh_supported ; then
0050 echo "EEH not supported on this system, skipping"
0051 exit $KSELFTESTS_SKIP;
0052 fi
0053
0054 if [ ! -e "/sys/kernel/debug/powerpc/eeh_dev_check" ] && \
0055 [ ! -e "/sys/kernel/debug/powerpc/eeh_dev_break" ] ; then
0056 log "debugfs EEH testing files are missing. Is debugfs mounted?"
0057 exit $KSELFTESTS_SKIP;
0058 fi
0059
0060
0061
0062 echo 5000 > /sys/kernel/debug/powerpc/eeh_max_freezes
0063 }
0064
0065 eeh_can_break() {
0066
0067 if [ -e "/sys/bus/pci/devices/$dev/pci_bus" ] ; then
0068 log "$dev, Skipped: bridge"
0069 return 1;
0070 fi
0071
0072
0073
0074
0075
0076 if [ "ahci" = "$(basename $(realpath /sys/bus/pci/devices/$dev/driver))" ] ; then
0077 log "$dev, Skipped: ahci doesn't support recovery"
0078 return 1;
0079 fi
0080
0081
0082
0083
0084
0085
0086 if ! pe_ok $dev ; then
0087 log "$dev, Skipped: Bad initial PE state"
0088 return 1;
0089 fi
0090
0091 return 0
0092 }
0093
0094 eeh_one_dev() {
0095 local dev="$1"
0096
0097
0098
0099
0100 if ! test -e /sys/bus/pci/devices/$dev/ ; then
0101 log "Error: '$dev' must be a sysfs device name (DDDD:BB:DD.F)"
0102 return 1;
0103 fi
0104
0105
0106 echo $dev >/sys/kernel/debug/powerpc/eeh_dev_break
0107
0108
0109
0110
0111 echo $dev >/sys/kernel/debug/powerpc/eeh_dev_check
0112
0113
0114
0115
0116
0117
0118
0119 max_wait=${EEH_MAX_WAIT:=60}
0120
0121 for i in `seq 0 ${max_wait}` ; do
0122 if pe_ok $dev ; then
0123 break;
0124 fi
0125 log "$dev, waited $i/${max_wait}"
0126 sleep 1
0127 done
0128
0129 if ! pe_ok $dev ; then
0130 log "$dev, Failed to recover!"
0131 return 1;
0132 fi
0133
0134 log "$dev, Recovered after $i seconds"
0135 return 0;
0136 }
0137
0138 eeh_has_driver() {
0139 test -e /sys/bus/pci/devices/$1/driver;
0140 return $?
0141 }
0142
0143 eeh_can_recover() {
0144
0145
0146 echo $1 > '/sys/kernel/debug/powerpc/eeh_dev_can_recover' 2>/dev/null
0147
0148 return $?
0149 }
0150
0151 eeh_find_all_pfs() {
0152 devices=""
0153
0154
0155 is_pseries=""
0156 if grep -q pSeries /proc/cpuinfo ; then
0157 if [ ! -f /proc/device-tree/rtas/ibm,open-sriov-allow-unfreeze ] ||
0158 [ ! -f /proc/device-tree/rtas/ibm,open-sriov-map-pe-number ] ; then
0159 return 1;
0160 fi
0161
0162 is_pseries="true"
0163 fi
0164
0165 for dev in `ls -1 /sys/bus/pci/devices/` ; do
0166 sysfs="/sys/bus/pci/devices/$dev"
0167 if [ ! -e "$sysfs/sriov_numvfs" ] ; then
0168 continue
0169 fi
0170
0171
0172 if [ -z "$is_pseries" ] &&
0173 [ ! -f "$sysfs/of_node/ibm,is-open-sriov-pf" ] &&
0174 [ ! -f "$sysfs/of_node/ibm,open-sriov-vf-bar-info" ] ; then
0175 continue;
0176 fi
0177
0178
0179 if ! eeh_has_driver $dev ; then
0180 continue
0181 fi
0182
0183 devices="$devices $dev"
0184 done
0185
0186 if [ -z "$devices" ] ; then
0187 return 1;
0188 fi
0189
0190 echo $devices
0191 return 0;
0192 }
0193
0194
0195
0196
0197 eeh_enable_vfs() {
0198 pf_list="$(eeh_find_all_pfs)"
0199
0200 vfs=0
0201 for dev in $pf_list ; do
0202 pf_sysfs="/sys/bus/pci/devices/$dev"
0203
0204
0205 echo 0 > "$pf_sysfs/sriov_numvfs"
0206 echo 1 > "$pf_sysfs/sriov_numvfs"
0207 if [ "$?" != 0 ] ; then
0208 log "Unable to enable VFs on $pf, skipping"
0209 continue;
0210 fi
0211
0212 vf="$(basename $(realpath "$pf_sysfs/virtfn0"))"
0213 if [ $? != 0 ] ; then
0214 log "unable to find enabled vf on $pf"
0215 echo 0 > "$pf_sysfs/sriov_numvfs"
0216 continue;
0217 fi
0218
0219 if ! eeh_can_break $vf ; then
0220 log "skipping "
0221
0222 echo 0 > "$pf_sysfs/sriov_numvfs"
0223 continue;
0224 fi
0225
0226 vfs="$((vfs + 1))"
0227 echo $vf
0228 done
0229
0230 test "$vfs" != 0
0231 return $?
0232 }
0233
0234 eeh_disable_vfs() {
0235 pf_list="$(eeh_find_all_pfs)"
0236 if [ -z "$pf_list" ] ; then
0237 return 1;
0238 fi
0239
0240 for dev in $pf_list ; do
0241 echo 0 > "/sys/bus/pci/devices/$dev/sriov_numvfs"
0242 done
0243
0244 return 0;
0245 }