[device/celestica]: Update DX010 platform APIS on 201911 branch (#5416)
* [device/celestica]: DX010 platform API update (#4608) - Fix fancontrol.service path - Fix return temp format in thermal API - Improve init time in chassis API - Upgrade sfp API * [device/celestica]: Update DX010 reboot cause API (#4678) - Add more cases support in DX010 reboot cause API - Add Thermal Overload reboot cause support - Add new Watchdog reboot cause support * [device/celestica]: using sonic-py-common package
This commit is contained in:
parent
6ae77f87cc
commit
10534a39eb
@ -9,3 +9,5 @@ MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/
|
||||
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
||||
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
||||
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
||||
MAXTEMPCRIT=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=65 /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=75
|
||||
MAXTEMPTYPE=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=ASIC /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=CPU
|
||||
|
@ -9,4 +9,5 @@ MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/
|
||||
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
||||
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
||||
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
||||
|
||||
MAXTEMPCRIT=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=75 /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=75
|
||||
MAXTEMPTYPE=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=ASIC /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=CPU
|
||||
|
@ -1,2 +1,2 @@
|
||||
__all__ = ["platform", "chassis"]
|
||||
from sonic_platform import *
|
||||
import chassis
|
||||
import platform
|
||||
|
@ -8,20 +8,10 @@
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
try:
|
||||
import sys
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.fan import Fan
|
||||
from sonic_platform.psu import Psu
|
||||
from sonic_platform.component import Component
|
||||
from sonic_platform.thermal import Thermal
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.eeprom import Tlv
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -33,9 +23,9 @@ NUM_SFP = 32
|
||||
NUM_COMPONENT = 5
|
||||
RESET_REGISTER = "0x103"
|
||||
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
|
||||
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
|
||||
REBOOT_CAUSE_FILE = "reboot-cause.txt"
|
||||
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
|
||||
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
||||
|
||||
|
||||
@ -44,39 +34,54 @@ class Chassis(ChassisBase):
|
||||
|
||||
def __init__(self):
|
||||
ChassisBase.__init__(self)
|
||||
self.config_data = {}
|
||||
self._api_helper = APIHelper()
|
||||
self.sfp_module_initialized = False
|
||||
self.__initialize_eeprom()
|
||||
self.is_host = self._api_helper.is_host()
|
||||
|
||||
if not self.is_host:
|
||||
self.__initialize_fan()
|
||||
self.__initialize_psu()
|
||||
self.__initialize_thermals()
|
||||
else:
|
||||
self.__initialize_components()
|
||||
|
||||
def __initialize_sfp(self):
|
||||
from sonic_platform.sfp import Sfp
|
||||
for index in range(0, NUM_SFP):
|
||||
sfp = Sfp(index)
|
||||
self._sfp_list.append(sfp)
|
||||
self.sfp_module_initialized = True
|
||||
|
||||
def __initialize_psu(self):
|
||||
from sonic_platform.psu import Psu
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
def __initialize_fan(self):
|
||||
from sonic_platform.fan import Fan
|
||||
for fant_index in range(0, NUM_FAN_TRAY):
|
||||
for fan_index in range(0, NUM_FAN):
|
||||
fan = Fan(fant_index, fan_index)
|
||||
self._fan_list.append(fan)
|
||||
for index in range(0, NUM_PSU):
|
||||
psu = Psu(index)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
def __initialize_thermals(self):
|
||||
from sonic_platform.thermal import Thermal
|
||||
for index in range(0, NUM_THERMAL):
|
||||
thermal = Thermal(index)
|
||||
self._thermal_list.append(thermal)
|
||||
# sfp index start from 1
|
||||
for index in range(0, NUM_SFP):
|
||||
sfp = Sfp(index)
|
||||
self._sfp_list.append(sfp)
|
||||
|
||||
def __initialize_eeprom(self):
|
||||
from sonic_platform.eeprom import Tlv
|
||||
self._eeprom = Tlv()
|
||||
|
||||
def __initialize_components(self):
|
||||
from sonic_platform.component import Component
|
||||
for index in range(0, NUM_COMPONENT):
|
||||
component = Component(index)
|
||||
self._component_list.append(component)
|
||||
|
||||
self._eeprom = Tlv()
|
||||
|
||||
def __is_host(self):
|
||||
return os.system(HOST_CHK_CMD) == 0
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_base_mac(self):
|
||||
"""
|
||||
Retrieves the base MAC address for the chassis
|
||||
@ -107,44 +112,98 @@ class Chassis(ChassisBase):
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
|
||||
REBOOT_CAUSE_POWER_LOSS = "Power Loss"
|
||||
REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU"
|
||||
REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC"
|
||||
REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other"
|
||||
REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed"
|
||||
REBOOT_CAUSE_WATCHDOG = "Watchdog"
|
||||
REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other"
|
||||
REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware"
|
||||
|
||||
"""
|
||||
description = 'None'
|
||||
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
||||
|
||||
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host(
|
||||
) else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
|
||||
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host(
|
||||
) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
|
||||
|
||||
hw_reboot_cause = self._component_list[0].get_register_value(RESET_REGISTER)
|
||||
|
||||
sw_reboot_cause = self.__read_txt_file(
|
||||
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
|
||||
sw_reboot_cause = self._api_helper.read_txt_file(
|
||||
reboot_cause_path) or "Unknown"
|
||||
prev_sw_reboot_cause = self.__read_txt_file(
|
||||
prev_reboot_cause_path) or "Unknown"
|
||||
hw_reboot_cause = self._api_helper.get_cpld_reg_value(
|
||||
GETREG_PATH, RESET_REGISTER)
|
||||
|
||||
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
|
||||
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
|
||||
elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11":
|
||||
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
||||
description = sw_reboot_cause
|
||||
elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11":
|
||||
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
||||
description = prev_sw_reboot_cause
|
||||
elif hw_reboot_cause == "0x22":
|
||||
reboot_cause = self.REBOOT_CAUSE_WATCHDOG,
|
||||
else:
|
||||
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
||||
description = 'Unknown reason'
|
||||
prev_reboot_cause = {
|
||||
'0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'),
|
||||
'0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'),
|
||||
'0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'),
|
||||
'0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'),
|
||||
'0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''),
|
||||
'0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''),
|
||||
'0x77': (self.REBOOT_CAUSE_WATCHDOG, '')
|
||||
}.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason'))
|
||||
|
||||
return (reboot_cause, description)
|
||||
if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11':
|
||||
prev_reboot_cause = (
|
||||
self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause)
|
||||
|
||||
return prev_reboot_cause
|
||||
|
||||
##############################################################
|
||||
######################## SFP methods #########################
|
||||
##############################################################
|
||||
|
||||
def get_num_sfps(self):
|
||||
"""
|
||||
Retrieves the number of sfps available on this chassis
|
||||
Returns:
|
||||
An integer, the number of sfps available on this chassis
|
||||
"""
|
||||
if not self.sfp_module_initialized:
|
||||
self.__initialize_sfp()
|
||||
|
||||
return len(self._sfp_list)
|
||||
|
||||
def get_all_sfps(self):
|
||||
"""
|
||||
Retrieves all sfps available on this chassis
|
||||
Returns:
|
||||
A list of objects derived from SfpBase representing all sfps
|
||||
available on this chassis
|
||||
"""
|
||||
if not self.sfp_module_initialized:
|
||||
self.__initialize_sfp()
|
||||
|
||||
return self._sfp_list
|
||||
|
||||
def get_sfp(self, index):
|
||||
"""
|
||||
Retrieves sfp represented by (1-based) index <index>
|
||||
Args:
|
||||
index: An integer, the index (1-based) of the sfp to retrieve.
|
||||
The index should be the sequence of a physical port in a chassis,
|
||||
starting from 1.
|
||||
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
|
||||
Returns:
|
||||
An object dervied from SfpBase representing the specified sfp
|
||||
"""
|
||||
sfp = None
|
||||
if not self.sfp_module_initialized:
|
||||
self.__initialize_sfp()
|
||||
|
||||
try:
|
||||
# The index will start from 1
|
||||
sfp = self._sfp_list[index-1]
|
||||
except IndexError:
|
||||
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
||||
index, len(self._sfp_list)))
|
||||
return sfp
|
||||
|
||||
##############################################################
|
||||
####################### Other methods ########################
|
||||
##############################################################
|
||||
|
||||
def get_watchdog(self):
|
||||
"""
|
||||
@ -159,23 +218,46 @@ class Chassis(ChassisBase):
|
||||
|
||||
return self._watchdog
|
||||
|
||||
def get_sfp(self, index):
|
||||
"""
|
||||
Retrieves sfp represented by (1-based) index <index>
|
||||
Args:
|
||||
index: An integer, the index (1-based) of the sfp to retrieve.
|
||||
The index should be the sequence of a physical port in a chassis,
|
||||
starting from 1.
|
||||
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
|
||||
Returns:
|
||||
An object dervied from SfpBase representing the specified sfp
|
||||
"""
|
||||
sfp = None
|
||||
##############################################################
|
||||
###################### Device methods ########################
|
||||
##############################################################
|
||||
|
||||
try:
|
||||
# The index will start from 1
|
||||
sfp = self._sfp_list[index-1]
|
||||
except IndexError:
|
||||
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
||||
index, len(self._sfp_list)))
|
||||
return sfp
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
return self._api_helper.hwsku
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the Chassis
|
||||
Returns:
|
||||
bool: True if Chassis is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the device
|
||||
Returns:
|
||||
string: Model/part number of device
|
||||
"""
|
||||
return self._eeprom.get_pn()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the device
|
||||
Returns:
|
||||
string: Serial number of device
|
||||
"""
|
||||
return self.get_serial_number()
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
return True
|
||||
|
@ -8,14 +8,13 @@
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import shutil
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
from sonic_platform_base.component_base import ComponentBase
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -29,7 +28,8 @@ CPLD_ADDR_MAPPING = {
|
||||
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
|
||||
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
|
||||
COMPONENT_DES_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "Basic Input/Output System"]
|
||||
COMPONENT_DES_LIST = ["Used for managing the CPU",
|
||||
"Used for managing QSFP+ ports (1-10)", "Used for managing QSFP+ ports (11-20)", "Used for managing QSFP+ ports (22-32)", "Basic Input/Output System"]
|
||||
|
||||
|
||||
class Component(ComponentBase):
|
||||
@ -40,24 +40,9 @@ class Component(ComponentBase):
|
||||
def __init__(self, component_index):
|
||||
ComponentBase.__init__(self)
|
||||
self.index = component_index
|
||||
self._api_helper = APIHelper()
|
||||
self.name = self.get_name()
|
||||
|
||||
def __run_command(self, command):
|
||||
# Run bash command and print output to stdout
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
shlex.split(command), stdout=subprocess.PIPE)
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
if output == '' and process.poll() is not None:
|
||||
break
|
||||
rc = process.poll()
|
||||
if rc != 0:
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __get_bios_version(self):
|
||||
# Retrieves the BIOS firmware version
|
||||
try:
|
||||
|
@ -14,6 +14,7 @@ import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -38,13 +39,16 @@ PSU_I2C_MAPPING = {
|
||||
"addr": "5b"
|
||||
},
|
||||
}
|
||||
NULL_VAL = "N/A"
|
||||
|
||||
|
||||
class Fan(FanBase):
|
||||
"""Platform-specific Fan class"""
|
||||
|
||||
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
|
||||
FanBase.__init__(self)
|
||||
self.fan_index = fan_index
|
||||
self._api_helper = APIHelper()
|
||||
self.fan_tray_index = fan_tray_index
|
||||
self.is_psu_fan = is_psu_fan
|
||||
if self.is_psu_fan:
|
||||
@ -75,16 +79,6 @@ class Fan(FanBase):
|
||||
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
|
||||
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
|
||||
]
|
||||
FanBase.__init__(self)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __write_txt_file(self, file_path, value):
|
||||
try:
|
||||
@ -105,7 +99,7 @@ class Fan(FanBase):
|
||||
def __get_gpio_base(self):
|
||||
for r in os.listdir(GPIO_DIR):
|
||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
||||
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||
return int(r[8:], 10)
|
||||
return 216 # Reserve
|
||||
|
||||
@ -113,7 +107,7 @@ class Fan(FanBase):
|
||||
gpio_base = self.dx010_fan_gpio[0]['base']
|
||||
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
||||
gpio_file = gpio_dir + "/value"
|
||||
retval = self.__read_txt_file(gpio_file)
|
||||
retval = self._api_helper.read_txt_file(gpio_file)
|
||||
return retval.rstrip('\r\n')
|
||||
|
||||
def __set_gpio_value(self, pinnum, value=0):
|
||||
@ -154,7 +148,8 @@ class Fan(FanBase):
|
||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||
self.psu_hwmon_path, fan_speed_sysfs_name)
|
||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
||||
fan_speed_rpm = self._api_helper.read_txt_file(
|
||||
fan_speed_sysfs_path) or 0
|
||||
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
|
||||
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
|
||||
elif self.get_presence():
|
||||
@ -164,7 +159,7 @@ class Fan(FanBase):
|
||||
sysfs_path = "%s%s/%s" % (
|
||||
EMC2305_PATH, device, EMC2305_FAN_INPUT)
|
||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
||||
raw = self._api_helper.read_txt_file(sysfs_path).strip('\r\n')
|
||||
pwm = int(raw, 10) if raw else 0
|
||||
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
|
||||
|
||||
@ -183,19 +178,7 @@ class Fan(FanBase):
|
||||
0 : when PWM mode is use
|
||||
pwm : when pwm mode is not use
|
||||
"""
|
||||
target = 0
|
||||
if not self.is_psu_fan:
|
||||
chip = self.emc2305_chip_mapping[self.fan_index]
|
||||
device = chip['device']
|
||||
fan_index = chip['index_map']
|
||||
sysfs_path = "%s%s/%s" % (
|
||||
EMC2305_PATH, device, EMC2305_FAN_TARGET)
|
||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
||||
pwm = int(raw, 10) if raw else 0
|
||||
target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM)
|
||||
|
||||
return target
|
||||
return 'N/A'
|
||||
|
||||
def get_speed_tolerance(self):
|
||||
"""
|
||||
@ -284,11 +267,43 @@ class Fan(FanBase):
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the PSU
|
||||
Retrieves the presence of the FAN
|
||||
Returns:
|
||||
bool: True if PSU is present, False if not
|
||||
bool: True if FAN is present, False if not
|
||||
"""
|
||||
present_str = self.__get_gpio_value(
|
||||
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
|
||||
|
||||
return int(present_str, 10) == 0 if not self.is_psu_fan else True
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the device
|
||||
Returns:
|
||||
string: Model/part number of device
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return NULL_VAL
|
||||
|
||||
model = NULL_VAL
|
||||
return model
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the device
|
||||
Returns:
|
||||
string: Serial number of device
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return NULL_VAL
|
||||
|
||||
serial = NULL_VAL
|
||||
return serial
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
return self.get_presence() and self.get_speed() > 0
|
||||
|
134
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
134
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
from sonic_py_common import device_info
|
||||
from mmap import *
|
||||
|
||||
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
||||
EMPTY_STRING = ""
|
||||
|
||||
|
||||
class APIHelper():
|
||||
|
||||
def __init__(self):
|
||||
(self.platform, self.hwsku) = device_info.get_platform_and_hwsku()
|
||||
|
||||
def is_host(self):
|
||||
return os.system(HOST_CHK_CMD) == 0
|
||||
|
||||
def pci_get_value(self, resource, offset):
|
||||
status = True
|
||||
result = ""
|
||||
try:
|
||||
fd = os.open(resource, os.O_RDWR)
|
||||
mm = mmap(fd, 0)
|
||||
mm.seek(int(offset))
|
||||
read_data_stream = mm.read(4)
|
||||
result = struct.unpack('I', read_data_stream)
|
||||
except:
|
||||
status = False
|
||||
return status, result
|
||||
|
||||
def run_command(self, cmd):
|
||||
status = True
|
||||
result = ""
|
||||
try:
|
||||
p = subprocess.Popen(
|
||||
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
raw_data, err = p.communicate()
|
||||
if err == '':
|
||||
result = raw_data.strip()
|
||||
except:
|
||||
status = False
|
||||
return status, result
|
||||
|
||||
def run_interactive_command(self, cmd):
|
||||
try:
|
||||
os.system(cmd)
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def read_one_line_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.readline()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def write_txt_file(self, file_path, value):
|
||||
try:
|
||||
with open(file_path, 'w') as fd:
|
||||
fd.write(str(value))
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_cpld_reg_value(self, getreg_path, register):
|
||||
cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register)
|
||||
status, result = self.run_command(cmd)
|
||||
return result if status else None
|
||||
|
||||
def ipmi_raw(self, netfn, cmd):
|
||||
status = True
|
||||
result = ""
|
||||
try:
|
||||
cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd))
|
||||
p = subprocess.Popen(
|
||||
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
raw_data, err = p.communicate()
|
||||
if err == '':
|
||||
result = raw_data.strip()
|
||||
else:
|
||||
status = False
|
||||
except:
|
||||
status = False
|
||||
return status, result
|
||||
|
||||
def ipmi_fru_id(self, id, key=None):
|
||||
status = True
|
||||
result = ""
|
||||
try:
|
||||
cmd = "ipmitool fru print {}".format(str(
|
||||
id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key))
|
||||
|
||||
p = subprocess.Popen(
|
||||
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
raw_data, err = p.communicate()
|
||||
if err == '':
|
||||
result = raw_data.strip()
|
||||
else:
|
||||
status = False
|
||||
except:
|
||||
status = False
|
||||
return status, result
|
||||
|
||||
def ipmi_set_ss_thres(self, id, threshold_key, value):
|
||||
status = True
|
||||
result = ""
|
||||
try:
|
||||
cmd = "ipmitool sensor thresh '{}' {} {}".format(
|
||||
str(id), str(threshold_key), str(value))
|
||||
p = subprocess.Popen(
|
||||
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
raw_data, err = p.communicate()
|
||||
if err == '':
|
||||
result = raw_data.strip()
|
||||
else:
|
||||
status = False
|
||||
except:
|
||||
status = False
|
||||
return status, result
|
@ -14,6 +14,7 @@ import sonic_platform
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_platform.fan import Fan
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -41,6 +42,7 @@ class Psu(PsuBase):
|
||||
def __init__(self, psu_index):
|
||||
PsuBase.__init__(self)
|
||||
self.index = psu_index
|
||||
self._api_helper = APIHelper()
|
||||
self.green_led_path = GREEN_LED_PATH.format(self.index+1)
|
||||
self.dx010_psu_gpio = [
|
||||
{'base': self.__get_gpio_base()},
|
||||
@ -54,27 +56,18 @@ class Psu(PsuBase):
|
||||
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
|
||||
self._fan_list.append(fan)
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def __search_file_by_contain(self, directory, search_str, file_start):
|
||||
for dirpath, dirnames, files in os.walk(directory):
|
||||
for name in files:
|
||||
file_path = os.path.join(dirpath, name)
|
||||
if name.startswith(file_start) and search_str in self.__read_txt_file(file_path):
|
||||
if name.startswith(file_start) and search_str in self._api_helper.read_txt_file(file_path):
|
||||
return file_path
|
||||
return None
|
||||
|
||||
def __get_gpio_base(self):
|
||||
for r in os.listdir(GPIO_DIR):
|
||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
||||
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||
return int(r[8:], 10)
|
||||
return 216 # Reserve
|
||||
|
||||
@ -82,7 +75,7 @@ class Psu(PsuBase):
|
||||
gpio_base = self.dx010_psu_gpio[0]['base']
|
||||
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
|
||||
gpio_file = gpio_dir + "/value"
|
||||
retval = self.__read_txt_file(gpio_file)
|
||||
retval = self._api_helper.read_txt_file(gpio_file)
|
||||
return retval.rstrip('\r\n')
|
||||
|
||||
def get_voltage(self):
|
||||
@ -104,7 +97,7 @@ class Psu(PsuBase):
|
||||
in_num = filter(str.isdigit, basename)
|
||||
vout_path = os.path.join(
|
||||
dir_name, voltage_name.format(in_num))
|
||||
vout_val = self.__read_txt_file(vout_path)
|
||||
vout_val = self._api_helper.read_txt_file(vout_path)
|
||||
psu_voltage = float(vout_val) / 1000
|
||||
|
||||
return psu_voltage
|
||||
@ -127,7 +120,7 @@ class Psu(PsuBase):
|
||||
cur_num = filter(str.isdigit, basename)
|
||||
cur_path = os.path.join(
|
||||
dir_name, current_name.format(cur_num))
|
||||
cur_val = self.__read_txt_file(cur_path)
|
||||
cur_val = self._api_helper.read_txt_file(cur_path)
|
||||
psu_current = float(cur_val) / 1000
|
||||
|
||||
return psu_current
|
||||
@ -150,7 +143,7 @@ class Psu(PsuBase):
|
||||
pw_num = filter(str.isdigit, basename)
|
||||
pw_path = os.path.join(
|
||||
dir_name, current_name.format(pw_num))
|
||||
pw_val = self.__read_txt_file(pw_path)
|
||||
pw_val = self._api_helper.read_txt_file(pw_path)
|
||||
psu_power = float(pw_val) / 1000000
|
||||
|
||||
return psu_power
|
||||
@ -196,7 +189,7 @@ class Psu(PsuBase):
|
||||
Returns:
|
||||
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
||||
"""
|
||||
status = self.__read_txt_file(self.green_led_path)
|
||||
status = self._api_helper.read_txt_file(self.green_led_path)
|
||||
status_str = {
|
||||
'255': self.STATUS_LED_COLOR_GREEN,
|
||||
'0': self.STATUS_LED_COLOR_OFF
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ import os.path
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
@ -27,6 +28,7 @@ class Thermal(ThermalBase):
|
||||
|
||||
def __init__(self, thermal_index):
|
||||
self.index = thermal_index
|
||||
self._api_helper = APIHelper()
|
||||
|
||||
# Add thermal name
|
||||
self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
|
||||
@ -48,19 +50,11 @@ class Thermal(ThermalBase):
|
||||
self.ss_key = self.THERMAL_NAME_LIST[self.index]
|
||||
self.ss_index = 1
|
||||
|
||||
def __read_txt_file(self, file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as fd:
|
||||
data = fd.read()
|
||||
return data.strip()
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
def __get_temp(self, temp_file):
|
||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||
raw_temp = self.__read_txt_file(temp_file_path)
|
||||
raw_temp = self._api_helper.read_txt_file(temp_file_path)
|
||||
temp = float(raw_temp)/1000
|
||||
return "{:.3f}".format(temp)
|
||||
return float("{:.3f}".format(temp))
|
||||
|
||||
def __set_threshold(self, file_name, temperature):
|
||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||
|
@ -7,115 +7,79 @@
|
||||
#
|
||||
#############################################################################
|
||||
import ctypes
|
||||
import fcntl
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
import array
|
||||
|
||||
try:
|
||||
from sonic_platform_base.watchdog_base import WatchdogBase
|
||||
from helper import APIHelper
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
""" ioctl constants """
|
||||
IO_WRITE = 0x40000000
|
||||
IO_READ = 0x80000000
|
||||
IO_READ_WRITE = 0xC0000000
|
||||
IO_SIZE_INT = 0x00040000
|
||||
IO_SIZE_40 = 0x00280000
|
||||
IO_TYPE_WATCHDOG = ord('W') << 8
|
||||
|
||||
WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG
|
||||
WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG
|
||||
WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG
|
||||
|
||||
""" Watchdog ioctl commands """
|
||||
WDIOC_GETSUPPORT = 0 | WDR_40
|
||||
WDIOC_GETSTATUS = 1 | WDR_INT
|
||||
WDIOC_GETBOOTSTATUS = 2 | WDR_INT
|
||||
WDIOC_GETTEMP = 3 | WDR_INT
|
||||
WDIOC_SETOPTIONS = 4 | WDR_INT
|
||||
WDIOC_KEEPALIVE = 5 | WDR_INT
|
||||
WDIOC_SETTIMEOUT = 6 | WDWR_INT
|
||||
WDIOC_GETTIMEOUT = 7 | WDR_INT
|
||||
WDIOC_SETPRETIMEOUT = 8 | WDWR_INT
|
||||
WDIOC_GETPRETIMEOUT = 9 | WDR_INT
|
||||
WDIOC_GETTIMELEFT = 10 | WDR_INT
|
||||
|
||||
""" Watchdog status constants """
|
||||
WDIOS_DISABLECARD = 0x0001
|
||||
WDIOS_ENABLECARD = 0x0002
|
||||
|
||||
PLATFORM_CPLD_PATH = '/sys/devices/platform/dx010_cpld'
|
||||
GETREG_FILE = 'getreg'
|
||||
SETREG_FILE = 'setreg'
|
||||
WDT_ENABLE_REG = '0x141'
|
||||
WDT_TIMER_L_BIT_REG = '0x142'
|
||||
WDT_TIMER_M_BIT_REG = '0x143'
|
||||
WDT_TIMER_H_BIT_REG = '0x144'
|
||||
WDT_KEEP_ALVIVE_REG = '0x145'
|
||||
ENABLE_CMD = '0x1'
|
||||
DISABLE_CMD = '0x0'
|
||||
WDT_COMMON_ERROR = -1
|
||||
WD_MAIN_IDENTITY = "iTCO_wdt"
|
||||
WDT_SYSFS_PATH = "/sys/class/watchdog/"
|
||||
|
||||
|
||||
class Watchdog(WatchdogBase):
|
||||
|
||||
def __init__(self):
|
||||
# Init helper
|
||||
self._api_helper = APIHelper()
|
||||
|
||||
# Init cpld reg path
|
||||
self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE)
|
||||
self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE)
|
||||
|
||||
self.watchdog, self.wdt_main_dev_name = self._get_wdt()
|
||||
self.status_path = "/sys/class/watchdog/%s/status" % self.wdt_main_dev_name
|
||||
self.state_path = "/sys/class/watchdog/%s/state" % self.wdt_main_dev_name
|
||||
self.timeout_path = "/sys/class/watchdog/%s/timeout" % self.wdt_main_dev_name
|
||||
# Set default value
|
||||
self._disable()
|
||||
self.armed = False
|
||||
self.timeout = self._gettimeout(self.timeout_path)
|
||||
|
||||
def _is_wd_main(self, dev):
|
||||
"""
|
||||
Checks watchdog identity
|
||||
"""
|
||||
identity = self._read_file(
|
||||
"{}/{}/identity".format(WDT_SYSFS_PATH, dev))
|
||||
return identity == WD_MAIN_IDENTITY
|
||||
|
||||
def _get_wdt(self):
|
||||
"""
|
||||
Retrieves watchdog device
|
||||
"""
|
||||
wdt_main_dev_list = [dev for dev in os.listdir(
|
||||
"/dev/") if dev.startswith("watchdog") and self._is_wd_main(dev)]
|
||||
if not wdt_main_dev_list:
|
||||
return None
|
||||
wdt_main_dev_name = wdt_main_dev_list[0]
|
||||
watchdog_device_path = "/dev/{}".format(wdt_main_dev_name)
|
||||
watchdog = os.open(watchdog_device_path, os.O_RDWR)
|
||||
return watchdog, wdt_main_dev_name
|
||||
|
||||
def _read_file(self, file_path):
|
||||
"""
|
||||
Read text file
|
||||
"""
|
||||
try:
|
||||
with open(file_path, "r") as fd:
|
||||
txt = fd.read()
|
||||
except IOError:
|
||||
return WDT_COMMON_ERROR
|
||||
return txt.strip()
|
||||
self.timeout = self._gettimeout()
|
||||
|
||||
def _enable(self):
|
||||
"""
|
||||
Turn on the watchdog timer
|
||||
"""
|
||||
req = array.array('h', [WDIOS_ENABLECARD])
|
||||
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
|
||||
# echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg
|
||||
enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD)
|
||||
return self._api_helper.write_txt_file(self.setreg_path, enable_val)
|
||||
|
||||
def _disable(self):
|
||||
"""
|
||||
Turn off the watchdog timer
|
||||
"""
|
||||
req = array.array('h', [WDIOS_DISABLECARD])
|
||||
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
|
||||
# echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg
|
||||
disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD)
|
||||
return self._api_helper.write_txt_file(self.setreg_path, disable_val)
|
||||
|
||||
def _keepalive(self):
|
||||
"""
|
||||
Keep alive watchdog timer
|
||||
"""
|
||||
fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE)
|
||||
# echo 0x145 0x1 > /sys/devices/platform/dx010_cpld/setreg
|
||||
enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD)
|
||||
return self._api_helper.write_txt_file(self.setreg_path, enable_val)
|
||||
|
||||
def _get_level_hex(self, sub_hex):
|
||||
sub_hex_str = sub_hex.replace("x", "0")
|
||||
return hex(int(sub_hex_str, 16))
|
||||
|
||||
def _seconds_to_lmh_hex(self, seconds):
|
||||
ms = seconds*1000 # calculate timeout in ms format
|
||||
hex_str = hex(ms)
|
||||
l = self._get_level_hex(hex_str[-2:])
|
||||
m = self._get_level_hex(hex_str[-4:-2])
|
||||
h = self._get_level_hex(hex_str[-6:-4])
|
||||
return (l, m, h)
|
||||
|
||||
def _settimeout(self, seconds):
|
||||
"""
|
||||
@ -123,29 +87,35 @@ class Watchdog(WatchdogBase):
|
||||
@param seconds - timeout in seconds
|
||||
@return is the actual set timeout
|
||||
"""
|
||||
req = array.array('I', [seconds])
|
||||
fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True)
|
||||
return int(req[0])
|
||||
# max = 0xffffff = 16777.215 seconds
|
||||
|
||||
def _gettimeout(self, timeout_path):
|
||||
(l, m, h) = self._seconds_to_lmh_hex(seconds)
|
||||
set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h)
|
||||
set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m)
|
||||
set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l)
|
||||
|
||||
self._api_helper.write_txt_file(self.setreg_path, set_h_val)
|
||||
self._api_helper.write_txt_file(self.setreg_path, set_m_val)
|
||||
self._api_helper.write_txt_file(self.setreg_path, set_l_val)
|
||||
|
||||
return seconds
|
||||
|
||||
def _gettimeout(self):
|
||||
"""
|
||||
Get watchdog timeout
|
||||
@return watchdog timeout
|
||||
"""
|
||||
req = array.array('I', [0])
|
||||
fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True)
|
||||
|
||||
return int(req[0])
|
||||
h_bit = self._api_helper.get_cpld_reg_value(
|
||||
self.getreg_path, WDT_TIMER_H_BIT_REG)
|
||||
m_bit = self._api_helper.get_cpld_reg_value(
|
||||
self.getreg_path, WDT_TIMER_M_BIT_REG)
|
||||
l_bit = self._api_helper.get_cpld_reg_value(
|
||||
self.getreg_path, WDT_TIMER_L_BIT_REG)
|
||||
|
||||
def _gettimeleft(self):
|
||||
"""
|
||||
Get time left before watchdog timer expires
|
||||
@return time left in seconds
|
||||
"""
|
||||
req = array.array('I', [0])
|
||||
fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True)
|
||||
|
||||
return int(req[0])
|
||||
hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:])
|
||||
ms = int(hex_time, 16)
|
||||
return int(float(ms)/1000)
|
||||
|
||||
#################################################################
|
||||
|
||||
@ -169,12 +139,15 @@ class Watchdog(WatchdogBase):
|
||||
try:
|
||||
if self.timeout != seconds:
|
||||
self.timeout = self._settimeout(seconds)
|
||||
|
||||
if self.armed:
|
||||
self._keepalive()
|
||||
else:
|
||||
self._enable()
|
||||
self.armed = True
|
||||
|
||||
ret = self.timeout
|
||||
self.arm_timestamp = time.time()
|
||||
except IOError as e:
|
||||
pass
|
||||
|
||||
@ -215,19 +188,4 @@ class Watchdog(WatchdogBase):
|
||||
watchdog timer. If the watchdog is not armed, returns -1.
|
||||
"""
|
||||
|
||||
timeleft = WDT_COMMON_ERROR
|
||||
|
||||
if self.armed:
|
||||
try:
|
||||
timeleft = self._gettimeleft()
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
return timeleft
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
Close watchdog
|
||||
"""
|
||||
|
||||
os.close(self.watchdog)
|
||||
return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR
|
||||
|
@ -2,7 +2,8 @@ dx010/scripts/dx010_check_qsfp.sh usr/local/bin
|
||||
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
||||
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
||||
dx010/scripts/fancontrol.sh etc/init.d
|
||||
services/fancontrol/fancontrol.service lib/systemd/system
|
||||
dx010/scripts/fancontrol.service lib/systemd/system
|
||||
dx010/scripts/thermal_overload_control.sh usr/local/bin
|
||||
services/fancontrol/fancontrol usr/local/bin
|
||||
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
|
||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||
|
@ -1,7 +1,7 @@
|
||||
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
||||
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
||||
haliburton/script/fancontrol.sh etc/init.d
|
||||
services/fancontrol/fancontrol.service lib/systemd/system
|
||||
haliburton/script/fancontrol.service lib/systemd/system
|
||||
services/fancontrol/fancontrol usr/local/bin
|
||||
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
|
||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||
|
@ -76,42 +76,52 @@
|
||||
#define PORT_SFPP1 33
|
||||
#define PORT_SFPP2 34
|
||||
|
||||
#define PORT_ID_BANK1 0x210
|
||||
#define PORT_ID_BANK2 0x290
|
||||
#define PORT_ID_BANK3 0x390
|
||||
|
||||
#define OPCODE_ID_BANK1 0x211
|
||||
#define OPCODE_ID_BANK2 0x291
|
||||
#define OPCODE_ID_BANK3 0x391
|
||||
#define CPLD_I2C_CLK_100Khz_BIT BIT(6)
|
||||
#define CPLD_I2C_DATA_SZ_MASK GENMASK(7,4)
|
||||
#define CPLD_I2C_CMD_SZ_MASK GENMASK(1,0)
|
||||
#define CPLD_I2C_ERR BIT(7)
|
||||
#define CPLD_I2C_BUSY BIT(6)
|
||||
#define CPLD_I2C_RST_BIT BIT(0)
|
||||
#define CPLD_I2C_RESET 0
|
||||
#define CPLD_I2C_UNRESET 1
|
||||
#define CPLD_I2C_DATA_SZ_MAX 8
|
||||
#define CPLD_I2C_CMD_SZ_MAX 3
|
||||
|
||||
#define DEVADDR_ID_BANK1 0x212
|
||||
#define DEVADDR_ID_BANK2 0x292
|
||||
#define DEVADDR_ID_BANK3 0x392
|
||||
|
||||
#define CMDBYT_ID_BANK1 0x213
|
||||
#define CMDBYT_ID_BANK2 0x293
|
||||
#define CMDBYT_ID_BANK3 0x393
|
||||
#define CPLD_I2C_BANK1_BASE 0x210
|
||||
#define CPLD_I2C_BANK2_BASE 0x290
|
||||
#define CPLD_I2C_BANK3_BASE 0x390
|
||||
|
||||
#define WRITE_ID_BANK1 0x220
|
||||
#define WRITE_ID_BANK2 0x2A0
|
||||
#define WRITE_ID_BANK3 0x3A0
|
||||
#define I2C_PORT_ID 0x0
|
||||
#define I2C_OPCODE 0x1
|
||||
#define I2C_DEV_ADDR 0x2
|
||||
#define I2C_CMD_BYT0 0x3
|
||||
#define I2C_SSR 0x6
|
||||
#define I2C_WRITE_DATA 0x10
|
||||
#define I2C_READ_DATA 0x20
|
||||
|
||||
#define READ_ID_BANK1 0x230
|
||||
#define READ_ID_BANK2 0x2B0
|
||||
#define READ_ID_BANK3 0x3B0
|
||||
|
||||
#define SSRR_ID_BANK1 0x216
|
||||
#define SSRR_ID_BANK2 0x296
|
||||
#define SSRR_ID_BANK3 0x396
|
||||
|
||||
#define HST_CNTL2_QUICK 0x00
|
||||
#define HST_CNTL2_BYTE 0x01
|
||||
#define HST_CNTL2_BYTE_DATA 0x02
|
||||
#define HST_CNTL2_WORD_DATA 0x03
|
||||
#define HST_CNTL2_BLOCK 0x05
|
||||
/*
|
||||
* private data to send to I2C core
|
||||
*/
|
||||
struct current_xfer {
|
||||
u8 addr;
|
||||
u8 cmd[CPLD_I2C_CMD_SZ_MAX];
|
||||
u8 cmd_len;
|
||||
u8 data_len;
|
||||
union i2c_smbus_data *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* private data of I2C adapter
|
||||
* base_addr: Base address of this I2C adapter core.
|
||||
* port_id: The port ID, use to mux an i2c core to a font panel port.
|
||||
* current_xfer: The struct carry current data setup of current smbus transfer.
|
||||
*/
|
||||
struct dx010_i2c_data {
|
||||
int base_addr;
|
||||
int portid;
|
||||
struct current_xfer curr_xfer;
|
||||
};
|
||||
|
||||
struct dx010_cpld_data {
|
||||
@ -364,179 +374,210 @@ static struct platform_device cel_dx010_lpc_dev = {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Refactoring this function with helper functions.
|
||||
static s32 cpld_smbus_transfer(struct dx010_i2c_data *priv) {
|
||||
|
||||
/**
|
||||
* Read eeprom of QSFP device.
|
||||
* @param a i2c adapter.
|
||||
* @param addr address to read.
|
||||
* @param new_data QSFP port number struct.
|
||||
* @param cmd i2c command.
|
||||
* @return 0 if not error, else the error code.
|
||||
*/
|
||||
static int i2c_read_eeprom(struct i2c_adapter *a, u16 addr,
|
||||
struct dx010_i2c_data *new_data, u8 cmd, union i2c_smbus_data *data){
|
||||
u8 val;
|
||||
s32 error;
|
||||
unsigned long ioBase;
|
||||
short portid, opcode, devaddr, cmdbyte0, ssr, writedata, readdata;
|
||||
union i2c_smbus_data *data;
|
||||
|
||||
u32 reg;
|
||||
int ioBase=0;
|
||||
char byte;
|
||||
short temp;
|
||||
short portid, opcode, devaddr, cmdbyte0, ssrr, writedata, readdata;
|
||||
__u16 word_data;
|
||||
int error = -EIO;
|
||||
error = -EIO;
|
||||
|
||||
mutex_lock(&cpld_data->cpld_lock);
|
||||
|
||||
if (((new_data->portid >= PORT_BANK1_START)
|
||||
&& (new_data->portid <= PORT_BANK1_END))
|
||||
|| (new_data->portid == PORT_SFPP1)
|
||||
|| (new_data->portid == PORT_SFPP2))
|
||||
{
|
||||
portid = PORT_ID_BANK1;
|
||||
opcode = OPCODE_ID_BANK1;
|
||||
devaddr = DEVADDR_ID_BANK1;
|
||||
cmdbyte0 = CMDBYT_ID_BANK1;
|
||||
ssrr = SSRR_ID_BANK1;
|
||||
writedata = WRITE_ID_BANK1;
|
||||
readdata = READ_ID_BANK1;
|
||||
}else if ((new_data->portid >= PORT_BANK2_START) && (new_data->portid <= PORT_BANK2_END)){
|
||||
portid = PORT_ID_BANK2;
|
||||
opcode = OPCODE_ID_BANK2;
|
||||
devaddr = DEVADDR_ID_BANK2;
|
||||
cmdbyte0 = CMDBYT_ID_BANK2;
|
||||
ssrr = SSRR_ID_BANK2;
|
||||
writedata = WRITE_ID_BANK2;
|
||||
readdata = READ_ID_BANK2;
|
||||
}else if ((new_data->portid >= PORT_BANK3_START) && (new_data->portid <= PORT_BANK3_END)){
|
||||
portid = PORT_ID_BANK3;
|
||||
opcode = OPCODE_ID_BANK3;
|
||||
devaddr = DEVADDR_ID_BANK3;
|
||||
cmdbyte0 = CMDBYT_ID_BANK3;
|
||||
ssrr = SSRR_ID_BANK3;
|
||||
writedata = WRITE_ID_BANK3;
|
||||
readdata = READ_ID_BANK3;
|
||||
}else{
|
||||
/* Invalid parameter! */
|
||||
error = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ioBase = priv->base_addr;
|
||||
data = priv->curr_xfer.data;
|
||||
|
||||
while ((inb(ioBase + ssrr) & 0x40));
|
||||
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
|
||||
error = -EIO;
|
||||
/* Read error reset the port */
|
||||
outb(0x00, ioBase + ssrr);
|
||||
udelay(3000);
|
||||
outb(0x01, ioBase + ssrr);
|
||||
goto exit;
|
||||
}
|
||||
portid = ioBase + I2C_PORT_ID;
|
||||
opcode = ioBase + I2C_OPCODE;
|
||||
devaddr = ioBase + I2C_DEV_ADDR;
|
||||
cmdbyte0 = ioBase + I2C_CMD_BYT0;
|
||||
ssr = ioBase + I2C_SSR;
|
||||
writedata = ioBase + I2C_WRITE_DATA;
|
||||
readdata = ioBase + I2C_READ_DATA;
|
||||
|
||||
byte = 0x40 +new_data->portid;
|
||||
reg = cmd;
|
||||
outb(byte, ioBase + portid);
|
||||
outb(reg,ioBase + cmdbyte0);
|
||||
byte = 33;
|
||||
outb(byte, ioBase + opcode);
|
||||
addr = addr << 1;
|
||||
addr |= 0x01;
|
||||
outb(addr, ioBase + devaddr);
|
||||
while ((inb(ioBase + ssrr) & 0x40))
|
||||
{
|
||||
/* Wait for the core to be free */
|
||||
pr_debug("CPLD_I2C Wait busy bit(6) to be cleared\n");
|
||||
do {
|
||||
val = inb(ssr);
|
||||
if ((val & CPLD_I2C_BUSY) == 0)
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
} while (true); // Risky - add timeout
|
||||
|
||||
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
|
||||
/* Read error reset the port */
|
||||
error = -EIO;
|
||||
outb(0x00, ioBase + ssrr);
|
||||
/*
|
||||
* If any error happen here, we do soft-reset
|
||||
* and check the BUSY/ERROR again.
|
||||
*/
|
||||
pr_debug("CPLD_I2C Check error bit(7)\n");
|
||||
if (val & CPLD_I2C_ERR) {
|
||||
pr_debug("CPLD_I2C Error, try soft-reset\n");
|
||||
outb(CPLD_I2C_RESET, ssr);
|
||||
udelay(3000);
|
||||
outb(0x01, ioBase + ssrr);
|
||||
goto exit;
|
||||
outb(CPLD_I2C_UNRESET, ssr);
|
||||
|
||||
val = inb(ssr);
|
||||
if (val & (CPLD_I2C_BUSY | CPLD_I2C_ERR)) {
|
||||
pr_debug("CPLD_I2C Error, core busy after reset\n");
|
||||
error = -EIO;
|
||||
goto exit_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
temp = ioBase + readdata;
|
||||
word_data = inb(temp);
|
||||
word_data |= (inb(++temp) << 8);
|
||||
/* Configure PortID */
|
||||
val = priv->portid | CPLD_I2C_CLK_100Khz_BIT;
|
||||
outb(val, portid);
|
||||
pr_debug("CPLD_I2C Write PortID 0x%x\n", val);
|
||||
|
||||
mutex_unlock(&cpld_data->cpld_lock);
|
||||
data->word = word_data;
|
||||
return 0;
|
||||
/* Configure OP_Code */
|
||||
val = (priv->curr_xfer.data_len << 4) & CPLD_I2C_DATA_SZ_MASK;
|
||||
val |= (priv->curr_xfer.cmd_len & CPLD_I2C_CMD_SZ_MASK);
|
||||
outb(val, opcode);
|
||||
pr_debug("CPLD_I2C Write OP_Code 0x%x\n", val);
|
||||
|
||||
exit:
|
||||
/* Configure CMD_Byte */
|
||||
outb(priv->curr_xfer.cmd[0], cmdbyte0);
|
||||
pr_debug("CPLD_I2C Write CMD_Byte 0x%x\n", priv->curr_xfer.cmd[0]);
|
||||
|
||||
/* Configure write data buffer */
|
||||
if ((priv->curr_xfer.addr & BIT(0)) == I2C_SMBUS_WRITE){
|
||||
pr_debug("CPLD_I2C Write WR_DATA buffer\n");
|
||||
switch(priv->curr_xfer.data_len){
|
||||
case 1:
|
||||
outb(data->byte, writedata);
|
||||
break;
|
||||
case 2:
|
||||
outb(data->block[0], writedata);
|
||||
outb(data->block[1], ++writedata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start transfer, write the device address register */
|
||||
pr_debug("CPLD_I2C Write DEV_ADDR 0x%x\n", priv->curr_xfer.addr);
|
||||
outb(priv->curr_xfer.addr, devaddr);
|
||||
|
||||
/* Wait for transfer finish */
|
||||
pr_debug("CPLD_I2C Wait busy bit(6) to be cleared\n");
|
||||
do {
|
||||
val = inb(ssr);
|
||||
if ((val & CPLD_I2C_BUSY) == 0)
|
||||
break;
|
||||
udelay(100);
|
||||
} while (true); // Risky - add timeout
|
||||
|
||||
pr_debug("CPLD_I2C Check error bit(7)\n");
|
||||
if (val & CPLD_I2C_ERR) {
|
||||
error = -EIO;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
/* Get the data from buffer */
|
||||
if ((priv->curr_xfer.addr & BIT(0)) == I2C_SMBUS_READ){
|
||||
pr_debug("CPLD_I2C Read RD_DATA buffer\n");
|
||||
switch (priv->curr_xfer.data_len) {
|
||||
case 1:
|
||||
data->byte = inb(readdata);
|
||||
break;
|
||||
case 2:
|
||||
data->block[0] = inb(readdata);
|
||||
data->block[1] = inb(++readdata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
exit_unlock:
|
||||
pr_debug("CPLD_I2C Exit with %d\n", error);
|
||||
mutex_unlock(&cpld_data->cpld_lock);
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
static int dx010_i2c_access(struct i2c_adapter *a, u16 addr,
|
||||
unsigned short flags, char rw, u8 cmd,
|
||||
int size, union i2c_smbus_data *data)
|
||||
{
|
||||
/*
|
||||
* dx010_smbus_xfer - execute LPC-SMBus transfer
|
||||
* Returns a negative errno code else zero on success.
|
||||
*/
|
||||
static s32 dx010_smbus_xfer(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data *data) {
|
||||
|
||||
int error = 0;
|
||||
struct dx010_i2c_data *priv;
|
||||
|
||||
struct dx010_i2c_data *new_data;
|
||||
priv = i2c_get_adapdata(adap);
|
||||
|
||||
/* Write the command register */
|
||||
new_data = i2c_get_adapdata(a);
|
||||
pr_debug("smbus_xfer called RW:%x CMD:%x SIZE:0x%x",
|
||||
read_write, command, size);
|
||||
|
||||
priv->curr_xfer.addr = (addr << 1) | read_write;
|
||||
priv->curr_xfer.data = data;
|
||||
|
||||
/* Map the size to what the chip understands */
|
||||
switch (size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
size = HST_CNTL2_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
size = HST_CNTL2_BYTE;
|
||||
priv->curr_xfer.cmd_len = 0;
|
||||
priv->curr_xfer.data_len = 1;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
size = HST_CNTL2_BYTE_DATA;
|
||||
priv->curr_xfer.cmd_len = 1;
|
||||
priv->curr_xfer.data_len = 1;
|
||||
priv->curr_xfer.cmd[0] = command;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
size = HST_CNTL2_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
size = HST_CNTL2_BLOCK;
|
||||
priv->curr_xfer.cmd_len = 1;
|
||||
priv->curr_xfer.data_len = 2;
|
||||
priv->curr_xfer.cmd[0] = command;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&a->dev, "Unsupported transaction %d\n", size);
|
||||
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
|
||||
error = -EOPNOTSUPP;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */
|
||||
break;
|
||||
case HST_CNTL2_BYTE_DATA:
|
||||
break;
|
||||
case HST_CNTL2_WORD_DATA:
|
||||
if( 0 == i2c_read_eeprom(a,addr,new_data,cmd,data)){
|
||||
error = 0;
|
||||
}else{
|
||||
error = -EIO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
error = cpld_smbus_transfer(priv);
|
||||
|
||||
Done:
|
||||
return error;
|
||||
}
|
||||
|
||||
static u32 dx010_i2c_func(struct i2c_adapter *a)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
// TODO: Add support for I2C_FUNC_SMBUS_PROC_CALL and I2C_FUNC_SMBUS_I2C_BLOCK
|
||||
static u32 dx010_i2c_func(struct i2c_adapter *a) {
|
||||
return I2C_FUNC_SMBUS_READ_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm dx010_i2c_algorithm = {
|
||||
.smbus_xfer = dx010_i2c_access,
|
||||
.smbus_xfer = dx010_smbus_xfer,
|
||||
.functionality = dx010_i2c_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter *cel_dx010_i2c_init(struct platform_device *pdev, int portid)
|
||||
{
|
||||
int error;
|
||||
|
||||
int base_addr;
|
||||
struct i2c_adapter *new_adapter;
|
||||
struct dx010_i2c_data *new_data;
|
||||
struct dx010_i2c_data *priv;
|
||||
|
||||
switch (portid) {
|
||||
case PORT_SFPP1 ... PORT_SFPP2:
|
||||
case PORT_BANK1_START ... PORT_BANK1_END:
|
||||
base_addr = CPLD_I2C_BANK1_BASE;
|
||||
break;
|
||||
case PORT_BANK2_START ... PORT_BANK2_END:
|
||||
base_addr = CPLD_I2C_BANK2_BASE;
|
||||
break;
|
||||
case PORT_BANK3_START ... PORT_BANK3_END:
|
||||
base_addr = CPLD_I2C_BANK3_BASE;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Invalid port adapter ID: %d\n", portid);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
|
||||
if (!new_adapter)
|
||||
@ -544,25 +585,33 @@ static struct i2c_adapter * cel_dx010_i2c_init(struct platform_device *pdev, int
|
||||
|
||||
new_adapter->dev.parent = &pdev->dev;
|
||||
new_adapter->owner = THIS_MODULE;
|
||||
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
new_adapter->class = I2C_CLASS_DEPRECATED;
|
||||
new_adapter->algo = &dx010_i2c_algorithm;
|
||||
|
||||
snprintf(new_adapter->name, sizeof(new_adapter->name),
|
||||
"SMBus dx010 i2c Adapter portid@%04x", portid);
|
||||
"SMBus dx010 i2c Adapter port %d", portid);
|
||||
|
||||
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
|
||||
if (!new_data)
|
||||
return NULL;
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
goto free_adap;
|
||||
}
|
||||
|
||||
new_data->portid = portid;
|
||||
|
||||
i2c_set_adapdata(new_adapter,new_data);
|
||||
priv->portid = portid;
|
||||
priv->base_addr = base_addr;
|
||||
|
||||
i2c_set_adapdata(new_adapter, priv);
|
||||
error = i2c_add_adapter(new_adapter);
|
||||
if(error)
|
||||
return NULL;
|
||||
goto free_data;
|
||||
|
||||
return new_adapter;
|
||||
|
||||
free_adap:
|
||||
kzfree(new_adapter);
|
||||
free_data:
|
||||
kzfree(priv);
|
||||
error_exit:
|
||||
return NULL;
|
||||
};
|
||||
|
||||
static int cel_dx010_lpc_drv_probe(struct platform_device *pdev)
|
||||
|
@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=fan speed regulator
|
||||
After=platform-modules-dx010.service
|
||||
Before=pmon.service
|
||||
|
||||
[Service]
|
||||
ExecStart=-/etc/init.d/fancontrol.sh start
|
||||
ExecStop=-/etc/init.d/fancontrol.sh stop
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020-present Celestica. 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.
|
||||
#
|
||||
#
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
|
||||
SETREG_FILE=/sys/devices/platform/dx010_cpld/setreg
|
||||
TOVERREG=0x140
|
||||
CPUOVER=0xa1
|
||||
ASICOVER=0xa2
|
||||
|
||||
prog="$0"
|
||||
command="$1"
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
usage() {
|
||||
echo "Usage: thermal_overload_control.sh [option] <command>"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " -h, --help : to print this message."
|
||||
echo
|
||||
echo "Commands:"
|
||||
echo
|
||||
echo " cpu: To enabling CPU thermal overload handler"
|
||||
echo
|
||||
echo " asic : To enabling ASIC thermal overload handler"
|
||||
echo
|
||||
}
|
||||
|
||||
cpu_overload() {
|
||||
logger "Enable CPU thermal overload control"
|
||||
set_reg=`echo ${TOVERREG} ${CPUOVER} > ${SETREG_FILE}`
|
||||
}
|
||||
|
||||
asic_overload() {
|
||||
logger "Enable ASIC thermal overload control"
|
||||
set_reg=`echo ${TOVERREG} ${ASICOVER} > ${SETREG_FILE}`
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
usage
|
||||
exit -1
|
||||
fi
|
||||
|
||||
case "$command" in
|
||||
-h | --help)
|
||||
usage
|
||||
;;
|
||||
cpu)
|
||||
cpu_overload
|
||||
;;
|
||||
asic)
|
||||
asic_overload
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit -1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $?
|
@ -39,6 +39,7 @@
|
||||
#
|
||||
|
||||
PIDFILE="/var/run/fancontrol.pid"
|
||||
THERMAL_OVERLOAD_CONTROL_FILE="/usr/local/bin/thermal_overload_control.sh"
|
||||
|
||||
#DEBUG=1
|
||||
MAX=255
|
||||
@ -68,6 +69,8 @@ function LoadConfig
|
||||
MINPWM=`egrep '^MINPWM=.*$' $1 | sed -e 's/MINPWM=//g'`
|
||||
MAXPWM=`egrep '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM=//g'`
|
||||
THYST=`egrep '^THYST=.*$' $1 | sed -e 's/THYST=//g'`
|
||||
MAXTEMPCRIT=`egrep '^MAXTEMPCRIT=.*$' $1 | sed -e 's/MAXTEMPCRIT=//g'`
|
||||
MAXTEMPTYPE=`egrep '^MAXTEMPTYPE=.*$' $1 | sed -e 's/MAXTEMPTYPE=//g'`
|
||||
echo
|
||||
# Check whether all mandatory settings are set
|
||||
if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]
|
||||
@ -158,6 +161,23 @@ function LoadConfig
|
||||
let fcvcount=fcvcount+1
|
||||
done
|
||||
echo
|
||||
|
||||
|
||||
let tscount=0
|
||||
for ts in $MAXTEMPCRIT
|
||||
do
|
||||
CSTEMP[$tscount]=`echo $ts | cut -d '=' -f1`
|
||||
CSMAXTEMPCRIT[$tscount]=`echo $ts | cut -d '=' -f2`
|
||||
CSMAXTEMPTYPE=($(echo $MAXTEMPTYPE |sed -e 's/ /\n/g'| cut -d'=' -f2))
|
||||
|
||||
echo
|
||||
echo "Settings for ${CSMAXTEMPTYPE[$tscount]} temperature sensor:"
|
||||
echo " Depends on ${CSTEMP[$tscount]}"
|
||||
echo " MAXTEMPCRIT=${CSMAXTEMPCRIT[$tscount]}"
|
||||
let tscount=tscount+1
|
||||
done
|
||||
echo
|
||||
|
||||
}
|
||||
|
||||
function CheckFanFault()
|
||||
@ -175,6 +195,28 @@ function CheckFanFault()
|
||||
return 0
|
||||
}
|
||||
|
||||
function CheckTempOver()
|
||||
{
|
||||
let tempcount=0
|
||||
while (( $tempcount < ${#CSTEMP[@]} )) # go through all temp.
|
||||
do
|
||||
ctemp=`cat ${CSTEMP[$tempcount]}`
|
||||
let maxcrit="${CSMAXTEMPCRIT[$tempcount]}*1000"
|
||||
if [ $ctemp -ge $maxcrit ]
|
||||
then
|
||||
logger "Thermal overload : ${CSMAXTEMPTYPE[$tempcount]} temperature ${ctemp} > ${maxcrit}"
|
||||
if [ -f "$THERMAL_OVERLOAD_CONTROL_FILE" ]
|
||||
then
|
||||
toc_cmd="${THERMAL_OVERLOAD_CONTROL_FILE} ${CSMAXTEMPTYPE[$tempcount],,}"
|
||||
bash $toc_cmd
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
let tempcount=$tempcount+1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
function DevicePath()
|
||||
{
|
||||
if [ -h "$1/device" ]
|
||||
@ -475,6 +517,9 @@ function UpdateFanSpeeds
|
||||
continue
|
||||
fi
|
||||
|
||||
#check thermal overload
|
||||
CheckTempOver
|
||||
|
||||
read tval < ${tsens}
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
|
Loading…
Reference in New Issue
Block a user