[platform/cel]: Backport reboot cause API to 201811 branch (#4619)
Add reboot cause API to support process-reboot-cause.service Implement chassis.get_reboot_cause platform API
This commit is contained in:
parent
236707ac64
commit
9f8d691d4e
@ -0,0 +1,2 @@
|
|||||||
|
import chassis
|
||||||
|
import platform
|
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Celestica
|
||||||
|
#
|
||||||
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
|
# provides the Chassis information which are available in the platform
|
||||||
|
#
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
RESET_REGISTER = "0x103"
|
||||||
|
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||||
|
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
|
||||||
|
REBOOT_CAUSE_FILE = "reboot-cause.txt"
|
||||||
|
|
||||||
|
|
||||||
|
class Chassis(ChassisBase):
|
||||||
|
"""Platform-specific Chassis class"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
ChassisBase.__init__(self)
|
||||||
|
|
||||||
|
def __get_register_value(self, register):
|
||||||
|
# Retrieves the cpld register value
|
||||||
|
cmd = "echo {1} > {0}; cat {0}".format(GETREG_PATH, register)
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err is not '':
|
||||||
|
return None
|
||||||
|
return raw_data.strip()
|
||||||
|
|
||||||
|
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_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_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
|
||||||
|
sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown"
|
||||||
|
hw_reboot_cause = self.__get_register_value(RESET_REGISTER)
|
||||||
|
|
||||||
|
prev_reboot_cause = {
|
||||||
|
'0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'),
|
||||||
|
'0x22': (self.REBOOT_CAUSE_WATCHDOG, 'Watchdog reset'),
|
||||||
|
'0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU')
|
||||||
|
}.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason'))
|
||||||
|
|
||||||
|
if sw_reboot_cause != 'Unknown' and ( hw_reboot_cause == '0x11' or hw_reboot_cause == '0x33'):
|
||||||
|
prev_reboot_cause = (self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause)
|
||||||
|
|
||||||
|
return prev_reboot_cause
|
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Celestica
|
||||||
|
#
|
||||||
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
|
# provides the platform information
|
||||||
|
#
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_platform_base.platform_base import PlatformBase
|
||||||
|
from sonic_platform.chassis import Chassis
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class Platform(PlatformBase):
|
||||||
|
"""Platform-specific Platform class"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
PlatformBase.__init__(self)
|
||||||
|
self._chassis = Chassis()
|
@ -1,3 +1,5 @@
|
|||||||
dx010/scripts/dx010_check_qsfp.sh usr/local/bin
|
dx010/scripts/dx010_check_qsfp.sh usr/local/bin
|
||||||
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
||||||
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
||||||
|
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,3 +1,5 @@
|
|||||||
depmod -a
|
depmod -a
|
||||||
systemctl enable platform-modules-dx010.service
|
systemctl enable platform-modules-dx010.service
|
||||||
systemctl start platform-modules-dx010.service
|
systemctl start platform-modules-dx010.service
|
||||||
|
|
||||||
|
/usr/local/bin/platform_api_mgnt.sh install
|
||||||
|
@ -13,6 +13,9 @@ MODULE_DIRS:= dx010 haliburton
|
|||||||
override_dh_auto_build:
|
override_dh_auto_build:
|
||||||
(for mod in $(MODULE_DIRS); do \
|
(for mod in $(MODULE_DIRS); do \
|
||||||
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
|
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
|
||||||
|
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||||
|
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
|
||||||
|
cd $(MOD_SRC_DIR); \
|
||||||
done)
|
done)
|
||||||
|
|
||||||
override_dh_auto_install:
|
override_dh_auto_install:
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
|
|
||||||
#define DRIVER_NAME "dx010_cpld"
|
#define DRIVER_NAME "dx010_cpld"
|
||||||
|
|
||||||
|
#define CPLD1_VERSION_ADDR 0x100
|
||||||
|
#define CPLD2_VERSION_ADDR 0x200
|
||||||
|
#define CPLD3_VERSION_ADDR 0x280
|
||||||
|
#define CPLD4_VERSION_ADDR 0x300
|
||||||
|
#define CPLD5_VERSION_ADDR 0x380
|
||||||
|
|
||||||
|
|
||||||
#define RESET0108 0x250
|
#define RESET0108 0x250
|
||||||
#define RESET0910 0x251
|
#define RESET0910 0x251
|
||||||
#define RESET1118 0x2d0
|
#define RESET1118 0x2d0
|
||||||
@ -110,10 +117,36 @@ struct dx010_i2c_data {
|
|||||||
struct dx010_cpld_data {
|
struct dx010_cpld_data {
|
||||||
struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD];
|
struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD];
|
||||||
struct mutex cpld_lock;
|
struct mutex cpld_lock;
|
||||||
|
uint16_t read_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dx010_cpld_data *cpld_data;
|
struct dx010_cpld_data *cpld_data;
|
||||||
|
|
||||||
|
static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint16_t addr;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
addr = (uint16_t)strtoul(buf,&last,16);
|
||||||
|
if(addr == 0 && buf == last){
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
cpld_data->read_addr = addr;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t get_reset(struct device *dev, struct device_attribute *devattr,
|
static ssize_t get_reset(struct device *dev, struct device_attribute *devattr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
@ -134,6 +167,47 @@ static ssize_t get_reset(struct device *dev, struct device_attribute *devattr,
|
|||||||
return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff);
|
return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint16_t addr;
|
||||||
|
uint8_t value;
|
||||||
|
char *tok;
|
||||||
|
char clone[count];
|
||||||
|
char *pclone = clone;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
strcpy(clone, buf);
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
tok = strsep((char**)&pclone, " ");
|
||||||
|
if(tok == NULL){
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
addr = (uint16_t)strtoul(tok,&last,16);
|
||||||
|
if(addr == 0 && tok == last){
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = strsep((char**)&pclone, " ");
|
||||||
|
if(tok == NULL){
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
value = (uint8_t)strtoul(tok,&last,16);
|
||||||
|
if(value == 0 && tok == last){
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(value,addr);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr,
|
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
@ -248,12 +322,16 @@ static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr,
|
|||||||
return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff);
|
return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RW(getreg);
|
||||||
|
static DEVICE_ATTR_WO(setreg);
|
||||||
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset);
|
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset);
|
||||||
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode);
|
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode);
|
||||||
static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL);
|
static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL);
|
||||||
static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL);
|
static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL);
|
||||||
|
|
||||||
static struct attribute *dx010_lpc_attrs[] = {
|
static struct attribute *dx010_lpc_attrs[] = {
|
||||||
|
&dev_attr_getreg.attr,
|
||||||
|
&dev_attr_setreg.attr,
|
||||||
&dev_attr_qsfp_reset.attr,
|
&dev_attr_qsfp_reset.attr,
|
||||||
&dev_attr_qsfp_lpmode.attr,
|
&dev_attr_qsfp_lpmode.attr,
|
||||||
&dev_attr_qsfp_modprs.attr,
|
&dev_attr_qsfp_modprs.attr,
|
||||||
@ -499,6 +577,7 @@ static int cel_dx010_lpc_drv_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mutex_init(&cpld_data->cpld_lock);
|
mutex_init(&cpld_data->cpld_lock);
|
||||||
|
cpld_data->read_addr = CPLD1_VERSION_ADDR;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
if (unlikely(!res)) {
|
if (unlikely(!res)) {
|
||||||
|
34
platform/broadcom/sonic-platform-modules-cel/dx010/setup.py
Normal file
34
platform/broadcom/sonic-platform-modules-cel/dx010/setup.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
DEVICE_NAME = 'celestica'
|
||||||
|
HW_SKU = 'x86_64-cel_seastone-r0'
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='sonic-platform',
|
||||||
|
version='1.0',
|
||||||
|
description='SONiC platform API implementation on Celestica Platforms',
|
||||||
|
license='Apache 2.0',
|
||||||
|
author='SONiC Team',
|
||||||
|
author_email='linuxnetdev@microsoft.com',
|
||||||
|
url='https://github.com/Azure/sonic-buildimage',
|
||||||
|
maintainer='Wirut Getbamrung',
|
||||||
|
maintainer_email='wgetbumr@celestica.com',
|
||||||
|
packages=[
|
||||||
|
'sonic_platform',
|
||||||
|
],
|
||||||
|
package_dir={
|
||||||
|
'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)},
|
||||||
|
classifiers=[
|
||||||
|
'Development Status :: 3 - Alpha',
|
||||||
|
'Environment :: Plugins',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'Intended Audience :: Information Technology',
|
||||||
|
'Intended Audience :: System Administrators',
|
||||||
|
'License :: OSI Approved :: Apache Software License',
|
||||||
|
'Natural Language :: English',
|
||||||
|
'Operating System :: POSIX :: Linux',
|
||||||
|
'Programming Language :: Python :: 2.7',
|
||||||
|
'Topic :: Utilities',
|
||||||
|
],
|
||||||
|
keywords='sonic SONiC platform PLATFORM',
|
||||||
|
)
|
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PREV_REBOOT_CAUSE="/host/reboot-cause/"
|
||||||
|
DEVICE="/usr/share/sonic/device"
|
||||||
|
PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)
|
||||||
|
FILES=$DEVICE/$PLATFORM/api_files
|
||||||
|
|
||||||
|
install() {
|
||||||
|
# Install sonic-platform package
|
||||||
|
if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then
|
||||||
|
pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
# mount needed files for sonic-platform package
|
||||||
|
mkdir -p $FILES
|
||||||
|
|
||||||
|
mkdir -p $FILES/reboot-cause
|
||||||
|
mount -B $PREV_REBOOT_CAUSE $FILES/reboot-cause
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
# deinit sonic-platform package
|
||||||
|
umount -f $PREV_REBOOT_CAUSE $FILES/reboot-cause >/dev/null 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall() {
|
||||||
|
# Uninstall sonic-platform package
|
||||||
|
pip uninstall -y sonic-platform >/dev/null 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
install | uninstall | init | deinit)
|
||||||
|
$1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {install|uninstall|init|deinit}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
Reference in New Issue
Block a user