Skip to content

Commit

Permalink
[DELL] S6100 Add PowerCycle Support for Last Reset Reason (#3402)
Browse files Browse the repository at this point in the history
* [DELL] S6100 Add PowerCycle Support for Last Reset Reason

* handle first time boot properly

* S6000 Last Reboot Reason Fix
  • Loading branch information
sridhar-ravindran authored and yxieca committed Sep 10, 2019
1 parent 614475f commit d4758af
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 9 deletions.
3 changes: 3 additions & 0 deletions files/image_config/platform/rc.local
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions files/image_config/process-reboot-cause/process-reboot-cause
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand Down
54 changes: 54 additions & 0 deletions platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)

Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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)

Expand Down

0 comments on commit d4758af

Please sign in to comment.