From 9f8d691d4e8b03e15d7685bca57d6f7296afb9b0 Mon Sep 17 00:00:00 2001 From: Wirut Getbamrung Date: Tue, 26 May 2020 16:27:03 +0700 Subject: [PATCH] [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 --- .../sonic_platform/__init__.py | 2 + .../sonic_platform/chassis.py | 71 +++++++++++++++++ .../sonic_platform/platform.py | 23 ++++++ .../debian/platform-modules-dx010.install | 2 + .../debian/platform-modules-dx010.postinst | 2 + .../sonic-platform-modules-cel/debian/rules | 3 + .../dx010/modules/dx010_cpld.c | 79 +++++++++++++++++++ .../sonic-platform-modules-cel/dx010/setup.py | 34 ++++++++ .../platform_api/platform_api_mgnt.sh | 41 ++++++++++ 9 files changed, 257 insertions(+) create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py create mode 100644 device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-cel/dx010/setup.py create mode 100755 platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..7b86fa12b515 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +import chassis +import platform diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..dd231c1de367 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py @@ -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 diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..a632de87e742 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py @@ -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() diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install index b25d47022b08..b88645a922ca 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install @@ -1,3 +1,5 @@ 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/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 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst index baff704171c7..bf7a120bb871 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst @@ -1,3 +1,5 @@ depmod -a systemctl enable platform-modules-dx010.service systemctl start platform-modules-dx010.service + +/usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules index 5086302b70b2..6f35290bce26 100755 --- a/platform/broadcom/sonic-platform-modules-cel/debian/rules +++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules @@ -13,6 +13,9 @@ MODULE_DIRS:= dx010 haliburton override_dh_auto_build: (for mod in $(MODULE_DIRS); do \ 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) override_dh_auto_install: diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c index 397361a5edd6..5e55b1190128 100644 --- a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c @@ -30,6 +30,13 @@ #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 RESET0910 0x251 #define RESET1118 0x2d0 @@ -110,10 +117,36 @@ struct dx010_i2c_data { struct dx010_cpld_data { struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD]; struct mutex cpld_lock; + uint16_t read_addr; }; 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, 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); } +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, 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); } +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_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL); static struct attribute *dx010_lpc_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, &dev_attr_qsfp_reset.attr, &dev_attr_qsfp_lpmode.attr, &dev_attr_qsfp_modprs.attr, @@ -499,6 +577,7 @@ static int cel_dx010_lpc_drv_probe(struct platform_device *pdev) return -ENOMEM; mutex_init(&cpld_data->cpld_lock); + cpld_data->read_addr = CPLD1_VERSION_ADDR; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (unlikely(!res)) { diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py b/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py new file mode 100644 index 000000000000..8183788184a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py @@ -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', +) diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh new file mode 100755 index 000000000000..e1d330357894 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh @@ -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