From d4758afddeeaad79dc4d3d1b66b4a325f3184dd5 Mon Sep 17 00:00:00 2001 From: sridhar-ravindran <45350577+sridhar-ravindran@users.noreply.github.com> Date: Tue, 10 Sep 2019 11:03:32 +0530 Subject: [PATCH] [DELL] S6100 Add PowerCycle Support for Last Reset Reason (#3402) * [DELL] S6100 Add PowerCycle Support for Last Reset Reason * handle first time boot properly * S6000 Last Reboot Reason Fix --- files/image_config/platform/rc.local | 3 ++ .../process-reboot-cause/process-reboot-cause | 14 +++++ .../common/dell_pmc.c | 54 +++++++++++++++++++ .../s6000/sonic_platform/chassis.py | 15 +++--- .../s6100/scripts/s6100_platform.sh | 19 +++++++ .../s6100/sonic_platform/chassis.py | 23 ++++++-- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local index 1df03718da3c..5ea98a8eccd9 100755 --- a/files/image_config/platform/rc.local +++ b/files/image_config/platform/rc.local @@ -235,6 +235,9 @@ if [ -f $FIRST_BOOT_FILE ]; then touch /tmp/pending_config_initialization fi + # Notify firstboot to Platform, to use it for reboot-cause + touch /tmp/notify_firstboot_to_platform + if [ -d /host/image-$SONIC_VERSION/platform/$platform ]; then dpkg -i /host/image-$SONIC_VERSION/platform/$platform/*.deb fi diff --git a/files/image_config/process-reboot-cause/process-reboot-cause b/files/image_config/process-reboot-cause/process-reboot-cause index 81c496a025ce..49cfa752641f 100755 --- a/files/image_config/process-reboot-cause/process-reboot-cause +++ b/files/image_config/process-reboot-cause/process-reboot-cause @@ -21,6 +21,7 @@ SYSLOG_IDENTIFIER = "process-reboot-cause" REBOOT_CAUSE_DIR = "/host/reboot-cause/" REBOOT_CAUSE_FILE = REBOOT_CAUSE_DIR + "reboot-cause.txt" PREVIOUS_REBOOT_CAUSE_FILE = REBOOT_CAUSE_DIR + "previous-reboot-cause.txt" +FIRST_BOOT_PLATFORM_FILE = "/tmp/notify_firstboot_to_platform" UNKNOWN_REBOOT_CAUSE = "Unknown" @@ -86,6 +87,13 @@ def main(): cause_file = open(REBOOT_CAUSE_FILE, "r") previous_reboot_cause = cause_file.readline().rstrip('\n') cause_file.close() + # If it is FirstTime Boot and previous_reboot_cause is unknown + # and hardware_reboot cause is non_hardware then + # Update the reboot cause as required + if os.path.isfile(FIRST_BOOT_PLATFORM_FILE): + if (previous_reboot_cause == UNKNOWN_REBOOT_CAUSE): + previous_reboot_cause = UNKNOWN_REBOOT_CAUSE + os.remove(FIRST_BOOT_PLATFORM_FILE) elif hardware_reboot_cause == chassis.REBOOT_CAUSE_HARDWARE_OTHER: previous_reboot_cause = "{} ({})".format(hardware_reboot_cause, optional_details) else: @@ -100,6 +108,12 @@ def main(): previous_reboot_cause = cause_file.readline().rstrip('\n') cause_file.close() + # If it is FirstTime Boot and previous_reboot_cause is unknown + # Update the reboot cause as required + if os.path.isfile(FIRST_BOOT_PLATFORM_FILE): + if (previous_reboot_cause == UNKNOWN_REBOOT_CAUSE): + previous_reboot_cause = UNKNOWN_REBOOT_CAUSE + os.remove(FIRST_BOOT_PLATFORM_FILE) # Write the previous reboot cause to PREVIOUS_REBOOT_CAUSE_FILE prev_cause_file = open(PREVIOUS_REBOOT_CAUSE_FILE, "w") prev_cause_file.write(previous_reboot_cause) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c index 141f41ba4a03..05cab626f135 100644 --- a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c @@ -43,6 +43,7 @@ #define IOREGION_LENGTH 0x4 #define SMF_ADDR_REG_OFFSET 0 #define SMF_READ_DATA_REG_OFFSET 2 +#define SMF_WRITE_DATA_REG_OFFSET 3 #define SMF_REG_ADDR 0x200 #define SMF_POR_SRC_REG 0x209 #define SMF_RST_SRC_REG 0x20A @@ -151,6 +152,8 @@ #define CPU_7_MONITOR_STATUS 0x02E8 #define CPU_8_MONITOR_STATUS 0x02E9 +/* Mailbox PowerOn Reason */ +#define TRACK_POWERON_REASON 0x05FF unsigned long *mmio; static struct kobject *dell_kobj; @@ -441,6 +444,18 @@ struct smf_sio_data { enum kinds kind; }; +static int smf_write_reg(struct smf_data *data, u16 reg, u16 dev_data) +{ + int res = 0; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + outb_p(dev_data & 0xff, data->addr + SMF_WRITE_DATA_REG_OFFSET); + mutex_unlock(&data->lock); + + return res; +} static int smf_read_reg(struct smf_data *data, u16 reg) { @@ -532,6 +547,40 @@ static ssize_t show_power_on_reason(struct device *dev, return sprintf(buf, "%x\n", ret); } +/* SMF Mailbox Power ON Reason */ +static ssize_t set_mb_poweron_reason(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + int err = 0; + unsigned int dev_data = 0; + struct smf_data *data = dev_get_drvdata(dev); + + err = kstrtouint(buf, 16, &dev_data); + if (err) + return err; + + err = smf_write_reg(data, TRACK_POWERON_REASON, dev_data); + + if(err < 0) + return err; + + return count; +} + +static ssize_t show_mb_poweron_reason(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + struct smf_data *data = dev_get_drvdata(dev); + + ret = smf_read_reg(data, TRACK_POWERON_REASON); + + if(ret < 0) + return ret; + + return sprintf(buf, "0x%x\n", ret); +} + /* FANIN ATTR */ static ssize_t show_fan_label(struct device *dev, struct device_attribute *attr, char *buf) @@ -1816,11 +1865,16 @@ static SENSOR_DEVICE_ATTR(smf_reset_reason, S_IRUGO, show_reset_reason, NULL, 1) static SENSOR_DEVICE_ATTR(smf_poweron_reason, S_IRUGO, show_power_on_reason, NULL, 1); +/* Mailbox Power tracking Reason */ +static SENSOR_DEVICE_ATTR(mb_poweron_reason, S_IRUGO|S_IWUSR, + show_mb_poweron_reason, set_mb_poweron_reason, 0); + static struct attribute *smf_dell_attrs[] = { &sensor_dev_attr_smf_version.dev_attr.attr, &sensor_dev_attr_smf_firmware_ver.dev_attr.attr, &sensor_dev_attr_smf_reset_reason.dev_attr.attr, &sensor_dev_attr_smf_poweron_reason.dev_attr.attr, + &sensor_dev_attr_mb_poweron_reason.dev_attr.attr, &sensor_dev_attr_fan_tray_presence.dev_attr.attr, &sensor_dev_attr_fan1_airflow.dev_attr.attr, &sensor_dev_attr_fan3_airflow.dev_attr.attr, diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py index b1046d9310f8..48ac70377877 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -28,7 +28,7 @@ class Chassis(ChassisBase): def __init__(self): ChassisBase.__init__(self) - def get_register(self, reg_name): + def _get_register(self, reg_name): rv = 'ERR' mb_reg_file = self.MAILBOX_DIR+'/'+reg_name @@ -49,13 +49,16 @@ def get_reboot_cause(self): """ Retrieves the cause of the previous reboot """ - reset_reason = int(self.get_register('last_reboot_reason'), base=16) - # In S6000, We track the reboot reason by writing the reason in # NVRAM. Only Warmboot and Coldboot reason are supported here. + # Since it does not support any hardware reason, we return + # non_hardware as default - if (reset_reason in self.reset_reason_dict): - return (self.reset_reason_dict[reset_reason], None) + lrr = self._get_register('last_reboot_reason') + if (lrr != 'ERR'): + reset_reason = int(lrr, base=16) + if (reset_reason in self.reset_reason_dict): + return (self.reset_reason_dict[reset_reason], None) - return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh index 71a5d269fec0..974d0662d564 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh @@ -217,6 +217,24 @@ reset_muxes() { io_rd_wr.py --set --val 0xff --offset 0x20b } +track_reboot_reason() { + if [[ -d /sys/devices/platform/SMF.512/hwmon/ ]]; then + rv=$(cd /sys/devices/platform/SMF.512/hwmon/*; cat mb_poweron_reason) + reason=$(echo $rv | cut -d 'x' -f2) + if [ $reason == "ff" ]; then + cd /sys/devices/platform/SMF.512/hwmon/* + if [[ -e /tmp/notify_firstboot_to_platform ]]; then + echo 0x01 > mb_poweron_reason + else + echo 0xbb > mb_poweron_reason + fi + elif [ $reason == "bb" ] || [ $reason == "1" ]; then + cd /sys/devices/platform/SMF.512/hwmon/* + echo 0xaa > mb_poweron_reason + fi + fi +} + install_python_api_package() { device="/usr/share/sonic/device" platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) @@ -239,6 +257,7 @@ if [[ "$1" == "init" ]]; then modprobe dell_ich modprobe dell_s6100_iom_cpld modprobe dell_s6100_lpc + track_reboot_reason cpu_board_mux "new_device" switch_board_mux "new_device" diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py index 6245f8efdc0d..ea57f368914b 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -39,7 +39,14 @@ class Chassis(ChassisBase): def __init__(self): ChassisBase.__init__(self) - def get_pmc_register(self, reg_name): + def _get_reboot_reason_smf_register(self): + # Returns 0xAA on software reload + # Returns 0xFF on power-cycle + # Returns 0x01 on first-boot + smf_mb_reg_reason = self._get_pmc_register('mb_poweron_reason') + return int(smf_mb_reg_reason, 16) + + def _get_pmc_register(self, reg_name): rv = 'ERR' mb_reg_file = self.MAILBOX_DIR+'/'+reg_name @@ -61,8 +68,12 @@ def get_reboot_cause(self): """ Retrieves the cause of the previous reboot """ - reset_reason = int(self.get_pmc_register('smf_reset_reason')) - power_reason = int(self.get_pmc_register('smf_poweron_reason')) + reset_reason = int(self._get_pmc_register('smf_reset_reason')) + power_reason = int(self._get_pmc_register('smf_poweron_reason')) + smf_mb_reg_reason = self._get_reboot_reason_smf_register() + + if ((smf_mb_reg_reason == 0x01) and (power_reason == 0x11)): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) # Reset_Reason = 11 ==> PowerLoss # So return the reboot reason from Last Power_Reason Dictionary @@ -71,10 +82,16 @@ def get_reboot_cause(self): # checking key presence in dictionary else return # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason # registers returned invalid data + + # In S6100, if Reset_Reason is not 11 and smf_mb_reg_reason + # is ff or bb, then it is PowerLoss if (reset_reason == 11): if (power_reason in self.power_reason_dict): return (self.power_reason_dict[power_reason], None) else: + if ((smf_mb_reg_reason == 0xbb) or (smf_mb_reg_reason == 0xff)): + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + if (reset_reason in self.reset_reason_dict): return (self.reset_reason_dict[reset_reason], None)