Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Nokia ixs7215] Platform API 2.0 improvements #6787

Merged
merged 3 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions device/nokia/armhf-nokia_ixs7215_52x-r0/platform_reboot
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

function SafePwrCycle() {
sync ; sync
umount -fa > /dev/null 2&>1

# Write CPLD register to initiate cold reboot
sudo i2cset -f -y 0 0x41 0x10 0x00
}

SafePwrCycle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ chmod 644 /sys/class/i2c-adapter/i2c-0/0-0053/eeprom
echo eeprom 0x55 > /sys/class/i2c-adapter/i2c-0/new_device
echo eeprom 0x56 > /sys/class/i2c-adapter/i2c-0/new_device

# Enumerate psu eeprom devices
# Enumerate PSU eeprom devices
echo eeprom 0x51 > /sys/class/i2c-adapter/i2c-1/new_device
echo eeprom 0x52 > /sys/class/i2c-adapter/i2c-1/new_device

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
__all__ = ["platform", "chassis"]
from sonic_platform import *


Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ def get_model(self):
"""
return self._eeprom.part_number_str()

def get_serial(self):
"""
Retrieves the serial number of the chassis (Service tag)
Returns:
string: Serial number of chassis
"""
return self._eeprom.service_tag_str()

def get_status(self):
"""
Retrieves the operational status of the chassis
Expand Down Expand Up @@ -367,7 +375,7 @@ def get_watchdog(self):
sonic_logger.log_warning(" Fail to load watchdog {}".format(repr(e)))

return self._watchdog

def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

smbus_present = 1
try:
import smbus
except ImportError as e:
Expand All @@ -34,6 +35,7 @@ class Component(ComponentBase):
["System-CPLD", "Used for managing SFPs, LEDs, PSUs and FANs "],
["U-Boot", "Performs initialization during booting"],
]
CPLD_UPDATE_COMMAND = 'cp /usr/sbin/vme /tmp; cp {} /tmp; cd /tmp; ./vme {};'

def __init__(self, component_index):
self.index = component_index
Expand All @@ -55,12 +57,12 @@ def _get_command_result(self, cmdline):
def _get_cpld_version(self, cpld_number):

if smbus_present == 0:
cmdstatus, cpld_version = cmd.getstatusoutput('i2cget -y 0 0x41 0x2')
cmdstatus, cpld_version = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0x2')
else:
bus = smbus.SMBus(0)
DEVICE_ADDRESS = 0x41
DEVICE_REG = 0x2
cpld_version = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
cpld_version = str(bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG))

return str(int(cpld_version, 16))

Expand Down Expand Up @@ -93,7 +95,7 @@ def get_firmware_version(self):
return self._get_cpld_version(self.index)

if self.index == 1:
cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data U-Boot /dev/mtd0ro|head -1 | cut -c 1-30')
cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data U-Boot /dev/mtd0ro|head -1 | cut -d" " -f2-4')
return uboot_version

def install_firmware(self, image_path):
Expand All @@ -114,6 +116,18 @@ def install_firmware(self, image_path):
print("ERROR: the cpld image {} doesn't exist ".format(image_path))
return False

cmdline = self.CPLD_UPDATE_COMMAND.format(image_path, image_name)

success_flag = False

try:
subprocess.check_call(cmdline, stderr=subprocess.STDOUT, shell=True)
success_flag = True
except subprocess.CalledProcessError as e:
print("ERROR: Failed to upgrade CPLD: rc={}".format(e.returncode))

if success_flag:
print("INFO: Refresh or power cycle is required to finish CPLD installation")

return success_flag

Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
########################################################################
# Nokia IXR7220_D1
# Nokia IXS7215
#
# Module contains platform specific implementation of SONiC Platform
# Base API and provides the EEPROMs' information.
#
# The different EEPROMs available are as follows:
# - System EEPROM : Contains Serial number, Service tag, Base MA
# address, etc. in ONIE TlvInfo EEPROM format.
# - PSU EEPROM : Contains Serial number, Part number, Service Tag,
# PSU type, Revision.
# - Fan EEPROM : Contains Serial number, Part number, Service Tag,
# Fan type, Number of Fans in Fantray, Revision.
# - PSU EEPROM : Contains Model name and Part number.
# - Fan EEPROM : Contains Part number, Serial number, Manufacture Date,
# and Service Tag.
########################################################################


Expand All @@ -23,15 +22,9 @@

# PSU eeprom fields in format required by EepromDecoder
psu_eeprom_format = [
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
('Part Number', 's', 10), ('Part Num Revision', 's', 3),
('Mfg Test', 's', 2), ('Redundant copy', 's', 83), ('PSU Type', 's', 1),
('Fab Rev', 's', 2)
]

# Fan eeprom fields in format required by EepromDecoder
fan_eeprom_format = [
('Model', 's', 12), ('Serial Number', 's', 13)
('Model', 's', 15), ('burn', 'x', 1),
('Part Number', 's', 14), ('burn', 'x', 40),
('Serial Number', 's', 11)
]


Expand All @@ -48,25 +41,32 @@ def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0):
if self.is_sys_eeprom:
self.start_offset = 0
self.eeprom_path = self.I2C_DIR + "i2c-0/0-0053/eeprom"

# System EEPROM is in ONIE TlvInfo EEPROM format
super(Eeprom, self).__init__(self.eeprom_path,
self.start_offset, '', True)
self._load_system_eeprom()
else:
if self.is_psu_eeprom:
self.index = psu_index
self.start_offset = 6
self.start_offset = 18
self.eeprom_path = self.I2C_DIR \
+ "i2c-1/1-005{}/eeprom".format(2 - self.index)
+ "i2c-1/1-005{}/eeprom".format(self.index)
self.format = psu_eeprom_format

# Decode device eeprom as per specified format
EepromDecoder.__init__(self, self.eeprom_path, self.format,
self.start_offset, '', True)
else:
self.index = fan_index
self.start_offset = 13
self.start_offset = 0
self.eeprom_path = self.I2C_DIR \
+ "i2c-4{0}/4{0}-0050/eeprom".format(self.index - 1)
self.format = fan_eeprom_format
EepromDecoder.__init__(self, self.eeprom_path, self.format,
self.start_offset, '', True)
+ "i2c-0/0-005{}/eeprom".format(self.index + 4)

# Fan EEPROM is in ONIE TlvInfo EEPROM format
super(Eeprom, self).__init__(self.eeprom_path,
self.start_offset, '', True)

self._load_device_eeprom()

def _load_system_eeprom(self):
Expand All @@ -83,32 +83,32 @@ def _load_system_eeprom(self):
self.serial_number = 'NA'
self.part_number = 'NA'
self.model_str = 'NA'
self.serial = 'NA'
self.service_tag = 'NA'
self.eeprom_tlv_dict = dict()
else:
eeprom = self.eeprom_data
self.eeprom_tlv_dict = dict()

if not self.is_valid_tlvinfo_header(eeprom):
self.base_mac = 'NA'
self.serial_number = 'NA'
self.part_number = 'NA'
self.model_str = 'NA'
self.serial = 'NA'
self.service_tag = 'NA'
return

total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length

# Construct dictionary of eeprom TLV entries
self.eeprom_tlv_dict = dict()
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break

tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])

name, value = self.decoder(None, tlv)

self.eeprom_tlv_dict[code] = value
Expand All @@ -118,56 +118,98 @@ def _load_system_eeprom(self):
tlv_index += eeprom[tlv_index+1] + 2

self.base_mac = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_MAC_BASE), 'NA')
"0x%X" % (self._TLV_CODE_MAC_BASE), 'NA')
self.serial_number = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
"0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
self.part_number = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA')
"0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA')
self.model_str = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA')
self.serial = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA')
"0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA')
self.service_tag = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA')

def _load_device_eeprom(self):
"""
Reads the Fan/PSU EEPROM and retrieves the serial number and
model number of the device.
Reads the Fan/PSU EEPROM and interprets as per the specified format
"""
try:
# Read Fan/PSU EEPROM as per the specified format.
self.eeprom_data = EepromDecoder.read_eeprom(self)
except Exception as e:
self.serial_number = 'NA'
self.part_number = 'NA'
self.model_str = 'NA'
self.serial = 'NA'
else:
self.serial_number = 'NA'
self.part_number = 'NA'
self.model_str = 'NA'
self.service_tag = 'NA'
self.mfg_date = 'NA'

# PSU device eeproms use proprietary format
if self.is_psu_eeprom:
try:
# Read Fan/PSU EEPROM as per the specified format.
self.eeprom_data = EepromDecoder.read_eeprom(self)
except Exception as e:
return

# Bail out if PSU eeprom unavailable
if self.eeprom_data[0] == 255:
return

(valid, data) = self._get_eeprom_field("Model")
if valid:
self.model_str = data
else:
self.model_str = 'NA'
self.model_str = data.decode()

(valid, data) = self._get_eeprom_field("Serial Number")
(valid, data) = self._get_eeprom_field("Part Number")
if valid:
self.serial_number = data
else:
self.serial_number = 'NA'
self.part_number = data.decode()

if self.is_psu_eeprom:
(valid, data) = self._get_eeprom_field("PSU Type")
# Early PSU device eeproms were not programmed with serial #
try:
(valid, data) = self._get_eeprom_field("Serial Number")
if valid:
self.psu_type = data
else:
self.psu_type = 'NA'
else:
(valid, data) = self._get_eeprom_field("Fan Type")
if valid:
self.fan_type = data
else:
self.fan_type = 'NA'
self.serial_number = data.decode()
except Exception as e:
return

# Fan device eeproms use ONIE TLV format
else:
try:
# Read Fan EEPROM as per ONIE TlvInfo EEPROM format.
self.eeprom_data = self.read_eeprom()
except Exception as e:
return

eeprom = self.eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return

total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length

# Construct dictionary of eeprom TLV entries
self.eeprom_tlv_dict = dict()
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break

tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])

name, value = self.decoder(None, tlv)

self.eeprom_tlv_dict[code] = value
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
break

tlv_index += eeprom[tlv_index+1] + 2

self.serial_number = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
self.part_number = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA')
self.model_str = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA')
self.service_tag = self.eeprom_tlv_dict.get(
"0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA')

def _get_eeprom_field(self, field_name):
def _get_eeprom_field(self, field_name, decode=False):
"""
For a field name specified in the EEPROM format, returns the
presence of the field and the value for the same.
Expand Down Expand Up @@ -205,24 +247,23 @@ def airflow_fan_type(self):
else:
return int(self.fan_type.encode('hex'), 16)

# System EEPROM specific methods
def base_mac_addr(self):
"""
Returns the base MAC address found in the system EEPROM.
"""
return self.base_mac

def modelstr(self):
"""
Returns the Model name.
"""
return self.model_str

def serial_str(self):
def base_mac_addr(self):
"""
Returns the base MAC address found in the system EEPROM.
"""
return self.base_mac

def service_tag_str(self):
"""
Returns the servicetag number.
"""
return self.serial
return self.service_tag

def system_eeprom_info(self):
"""
Expand Down
Loading