Skip to content

Commit

Permalink
ELBERT: fscd: Add inital fscd scripts (#97)
Browse files Browse the repository at this point in the history
Summary:
ELBERT: fscd: Add inital fscd scripts

- Add set_fan_speed, get_fan_speed script
- Add placeholder fscd config profile. Currently this has dummy values and is not used
- FSCD is not actually turned on yet as we waiting for thermal data
- Fancpld typo fixed

Testing:
root@bmc-oob:~# get_fan_speed.sh
Fan 1 RPMs: 7481, 7481, (30%)
Fan 2 RPMs: 7462, 7462, (30%)
Fan 3 RPMs: 7537, 7537, (30%)
Fan 4 RPMs: 7444, 7444, (30%)
Fan 5 RPMs: 7407, 7407, (30%)

root@bmc-oob:~# set_fan_speed.sh 100
255 will be set to /sys/bus/i2c/drivers/fancpld/6-0060/fan1_pwm !!!!
Successfully set fan 1 speed to 100%
255 will be set to /sys/bus/i2c/drivers/fancpld/6-0060/fan2_pwm !!!!
Successfully set fan 2 speed to 100%
255 will be set to /sys/bus/i2c/drivers/fancpld/6-0060/fan3_pwm !!!!
Successfully set fan 3 speed to 100%
255 will be set to /sys/bus/i2c/drivers/fancpld/6-0060/fan4_pwm !!!!
Successfully set fan 4 speed to 100%
255 will be set to /sys/bus/i2c/drivers/fancpld/6-0060/fan5_pwm !!!!
Successfully set fan 5 speed to 100%

root@bmc-oob:~# get_fan_speed.sh
Fan 1 RPMs: 14634, 14634, (100%)
Fan 2 RPMs: 14563, 14563, (100%)
Fan 3 RPMs: 14354, 14354, (100%)
Fan 4 RPMs: 14354, 14354, (100%)
Fan 5 RPMs: 14563, 14563, (100%)

Pull Request resolved: facebookexternal/openbmc.arista#97

Reviewed By: benwei13

fbshipit-source-id: a32d5e083e
  • Loading branch information
joancaneus authored and facebook-github-bot committed Oct 23, 2020
1 parent 5947c13 commit 5a77b78
Show file tree
Hide file tree
Showing 8 changed files with 470 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#endif

#define present_help_str \
"0x0: present\n" \
"0x1: not present"
"0x0: not present\n" \
"0x1: present"

#define led_bit_help_str \
"0x0: LED On\n" \
Expand All @@ -51,8 +51,8 @@

#define fan_id_change_bit_help_str \
"Fan ID change: Clear on writing '1'\n" \
"0x0: Fan ID changed\n" \
"0x1: Fan ID did not change."
"0x0: Fan ID did not change\n" \
"0x1: Fan ID changed."

#define fan_change_latched \
"0x1: Change latched (W0C)\n" \
Expand Down
132 changes: 132 additions & 0 deletions meta-facebook/meta-elbert/recipes-utils/fscd/fscd/fsc-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{
"pwm_transition_value": 50,
"pwm_boost_value": 100,
"sample_interval_ms": 3000,
"boost": {
"fan_fail": true,
"sensor_fail": false,
"progressive": true
},
"fan_dead_boost": {
"data": [
[1,100]
]
},
"watchdog": true,
"min_rpm": 800,
"profiles": {
"linear_inlet": {
"read_source" : {
"sysfs" : "/sys/bus/i2c/drivers/lm90/11-004c/hwmon/hwmon*/temp2_input"
},
"read_limit": {
"valid": {
"limit": 40,
"threshold": 20,
"action": "host_shutdown"
},
"invalid": {
"limit": -60,
"threshold": 10,
"action": "host_shutdown"
}
},
"type": "linear",
"positive_hysteresis": 0,
"negative_hysteresis": 1,
"data": [
[25, 100],
[30, 150],
[35, 185],
[36, 255]
]
},
"linear_th4": {
"read_source" : {
"sysfs" : "/sys/bus/i2c/drivers/max6697/4-004d/hwmon/hwmon*/temp2_input"
},
"read_limit": {
"valid": {
"limit": 110,
"threshold": 20,
"action": "host_shutdown"
},
"invalid": {
"limit": -60,
"threshold": 10,
"action": "host_shutdown"
}
},
"type": "linear",
"positive_hysteresis": 0,
"negative_hysteresis": 1,
"data": [
[15, 100],
[110, 255]
]
}
},
"fans": {
"1": {
"label" : "1",
"read_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan1_input"
},
"write_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan1_pwm",
"max_duty_register": 255
}
},
"2": {
"label" : "2",
"read_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan2_input"
},
"write_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan2_pwm",
"max_duty_register": 255
}
},
"3": {
"label" : "3",
"read_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan3_input"
},
"write_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan3_pwm",
"max_duty_register": 255
}
},
"4": {
"label" : "4",
"read_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan4_input"
},
"write_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan4_pwm",
"max_duty_register": 255
}
},
"5": {
"label" : "5",
"read_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan5_input"
},
"write_source" : {
"sysfs": "/sys/bus/i2c/drivers/fancpld/6-0060/fan5_pwm",
"max_duty_register": 255
}
}
},
"zones": {
"zone_1": {
"pwm_output": [1, 2, 3, 4, 5],
"expr_file": "zone1.fsc"
}
},
"notes": {
"fanx_pwm": {
"0_to_255" : "the range that corresponds to 0_to_100 percent"
}
}
}
146 changes: 146 additions & 0 deletions meta-facebook/meta-elbert/recipes-utils/fscd/fscd/fsc_board.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
import time
from subprocess import PIPE, Popen

from fsc_util import Logger


# Overrides the functions that need to do HW dependent
# actions, such as LED control, PWM full boost and
# emergency shutdown


def elbert_set_fan_led(fan, color="led_blue"):
FCM_CPLD = "/sys/bus/i2c/drivers/fancpld/6-0060/"
for fan in fan.split():
# ELBERT fans are all named as number
if not fan.isdigit():
break
fan = int(fan)
if fan > 5 or fan < 1:
break

# 1 means off
green_value = 1
red_value = 1
blue_value = 1
amber_value = 1
green_key = FCM_CPLD + "fan" + str(fan) + "_led_green"
red_key = FCM_CPLD + "fan" + str(fan) + "_led_red"
blue_key = FCM_CPLD + "fan" + str(fan) + "_led_blue"
amber_key = FCM_CPLD + "fan" + str(fan) + "_led_amber"

# 0 means on
if "red" in color:
red_value = 0
elif "blue" in color:
blue_value = 0
elif "green" in color:
green_value = 0
elif "amber" in color:
amber_value = 0
else:
return 0 # error

cmd_green = "echo " + str(green_value) + " > " + green_key
cmd_red = "echo " + str(red_value) + " > " + red_key
cmd_blue = "echo " + str(blue_value) + " > " + blue_key
cmd_amber = "echo " + str(amber_value) + " > " + amber_key

# Do the best effort. When LED setting commands fail, move on,
# as this failure alone will not damage or take down hardware
Popen(cmd_green, shell=True, stdout=PIPE).stdout.read()
Popen(cmd_red, shell=True, stdout=PIPE).stdout.read()
Popen(cmd_blue, shell=True, stdout=PIPE).stdout.read()
Popen(cmd_amber, shell=True, stdout=PIPE).stdout.read()
return 0


def board_fan_actions(fan, action="None"):
if "led" in action:
elbert_set_fan_led(fan.label, color=action)
else:
Logger.warn("fscd: %s has no action %s" % (fan.label, str(action)))
pass


def elbert_set_all_pwm(boost):
# The script name is same as Minipack.
# Note that, the argument to this script is in range [0,100]
# and the script will scale the value to [0,255]
cmd = "/usr/local/bin/set_fan_speed.sh %d" % (boost)
response = Popen(cmd, shell=True, stdout=PIPE).stdout.read()
return response


def board_callout(callout="None", **kwargs):
if "init_fans" in callout:
boost = 100
if "boost" in kwargs:
boost = kwargs["boost"]
Logger.info("FSC init fans to boost=%s " % str(boost))
return elbert_set_all_pwm(boost)
else:
Logger.warn("Need to perform callout action %s" % callout)
pass


# This function will run cmd_str and ignore any exception
# We use this function for shutdown sequence, as the system may
# be in a bad state where any command may fail
def elbert_force_run_cmd(cmd_str):
try:
Popen(cmd_str, shell=True, stdout=PIPE).stdout.read()
except Exception:
pass
return 0


def elbert_host_shutdown():
# Do the best effort by :
# 1. Turn off CPU
# 2. Then turn off SMB
# 3. Then turn off all PSU
# We do this because, if any one of CPLD/FPGA is already
# malfunctioning, we still want to turn off as much part of
# the system as possible.
SMB_POWER_REG = "/sys/bus/i2c/drivers/smbcpld/4-0023/smb_power_en"
CPU_OFF = "/usr/local/bin/wedge_power.sh off"
SMB_OFF = "echo 0 > " + SMB_POWER_REG
# First, turn off most of the switch board
Logger.info("host_shutdown() executing {}".format(SMB_OFF))
elbert_force_run_cmd(SMB_OFF)
time.sleep(3)
# Then, turn off X86 CPU
Logger.info("host_shutdown() executing {}".format(CPU_OFF))
elbert_force_run_cmd(CPU_OFF)

# Until FSCD is proven to be very stable on most versions of FSCD,
# we will only turn off SMB and BMC, but not PSUs.
# (When PSUs are all turned off, it's hard to recover in DC)

return 0


def board_host_actions(action="None", cause="None"):
if "host_shutdown" in action:
Logger.crit("Host is shutdown due to cause %s" % (str(cause),))
return elbert_host_shutdown()
Logger.warn("Host needs action '%s' and cause '%s'" % (str(action), str(cause)))
pass
65 changes: 65 additions & 0 deletions meta-facebook/meta-elbert/recipes-utils/fscd/fscd/get_fan_speed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/sh
#
# Copyright 2020-present Facebook. All Rights Reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#


usage() {
echo "Usage: $0 [Fan Unit (1..5)]" >&2
}

FCMCPLD="/sys/bus/i2c/drivers/fancpld/6-0060"

show_pwm()
{
pwm="$FCMCPLD/fan$1_pwm"
val="$(head -n 1 "$pwm")"
# Val is [0,255], so let's scale the value down to [0,100]
float_val=$(echo "$val 100 * 255 / p" | dc)
rounded="$(printf '%.*f' 0 "$float_val")"
echo "$rounded%"
}

show_rpm()
{
rpm="$(head -n 1 "$FCMCPLD"/fan"$1"_input)"
# Keep the output in the same format as Minipack
echo "$rpm, $rpm"
}

set -e

# If user input is given, use it as FAN TRAY instance
# Otherwise, read all
if [ "$#" -eq 0 ]; then
FANS="1 2 3 4 5"
elif [ "$#" -eq 1 ]; then
if [ "$1" -le 0 ] || [ "$1" -ge 6 ]; then
echo "Fan $1: Should be between 1 and 5"
exit 1
fi
FANS="$1"
else
usage
exit 1
fi


for fan in $FANS; do
echo "Fan $fan RPMs: $(show_rpm "$fan"), ($(show_pwm "$fan"))"
done
Loading

0 comments on commit 5a77b78

Please sign in to comment.