Skip to content

Commit 7ac590b

Browse files
keboliustephenxs
andauthored
[Mellanox] Enhance Platform API to support SN2201 - RJ45 ports and new components mgmt. (#10377)
* Support new platform SN2201 and RJ45 port Signed-off-by: Kebo Liu <[email protected]> * remove unused import and redundant function Signed-off-by: Kebo Liu <[email protected]> * fix error introduced by rebase Signed-off-by: Kebo Liu <[email protected]> * Revert the special handling of RJ45 ports (#56) * Revert the special handling of RJ45 ports sfp.py sfp_event.py chassis.py Signed-off-by: Stephen Sun <[email protected]> * Remove deadcode Signed-off-by: Stephen Sun <[email protected]> * Support CPLD update for SN2201 A new class is introduced, deriving from ComponentCPLD and overloading _install_firmware Change _install_firmware from private (starting with __) to protected, making it overloadable Signed-off-by: Stephen Sun <[email protected]> * Initialize component BIOS/CPLD Signed-off-by: Stephen Sun <[email protected]> * Remove swb_amb which doesn't on DVT board any more Signed-off-by: Stephen Sun <[email protected]> * Remove the unexisted sensor - switch board ambient - from platform.json Signed-off-by: Stephen Sun <[email protected]> * Do not report error on receiving unknown status on RJ45 ports Translate it to disconnect for RJ45 ports Report error for xSFP ports Signed-off-by: Stephen Sun <[email protected]> * Add reinit for RJ45 to avoid exception Signed-off-by: Stephen Sun <[email protected]> Co-authored-by: Stephen Sun <[email protected]> Co-authored-by: Stephen Sun <[email protected]>
1 parent fdc65d7 commit 7ac590b

File tree

15 files changed

+570
-65
lines changed

15 files changed

+570
-65
lines changed

device/mellanox/x86_64-nvidia_sn2201-r0/platform.json

-3
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,6 @@
9090
{
9191
"name": "Ambient CPU Board Temp"
9292
},
93-
{
94-
"name": "Ambient Switch Board Temp"
95-
},
9693
{
9794
"name": "CPU Pack Temp"
9895
},

device/mellanox/x86_64-nvidia_sn2201-r0/platform_components.json

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"component": {
55
"ONIE": { },
66
"SSD": { },
7+
"BIOS": { },
78
"CPLD1": { },
89
"CPLD2": { }
910
}

platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py

+25-8
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,17 @@
2727
from sonic_py_common.logger import Logger
2828
import os
2929
from functools import reduce
30-
30+
from .utils import extract_RJ45_ports_index
3131
from . import utils
3232
from .device_data import DeviceDataManager
33+
from .sfp import SFP, RJ45Port, deinitialize_sdk_handle
3334
except ImportError as e:
3435
raise ImportError (str(e) + "- required module not found")
3536

3637
MAX_SELECT_DELAY = 3600
3738

39+
RJ45_TYPE = "RJ45"
40+
3841
DMI_FILE = '/sys/firmware/dmi/entries/2-0/raw'
3942
DMI_HEADER_LEN = 15
4043
DMI_PRODUCT_NAME = "Product Name"
@@ -106,6 +109,10 @@ def __init__(self):
106109
self.sfp_initialized_count = 0
107110
self.sfp_event = None
108111
self.reboot_cause_initialized = False
112+
113+
# Build the RJ45 port list from platform.json and hwsku.json
114+
self.RJ45_port_list = extract_RJ45_ports_index()
115+
109116
logger.log_info("Chassis loaded successfully")
110117

111118
def __del__(self):
@@ -242,22 +249,31 @@ def initialize_single_sfp(self, index):
242249

243250
if not self._sfp_list[index]:
244251
from .sfp import SFP
245-
self._sfp_list[index] = SFP(index)
252+
if self.RJ45_port_list and index in self.RJ45_port_list:
253+
self._sfp_list[index] = RJ45Port(index)
254+
else:
255+
self._sfp_list[index] = SFP(index)
246256
self.sfp_initialized_count += 1
247257

248258
def initialize_sfp(self):
249259
if not self._sfp_list:
250260
from .sfp import SFP
251261
sfp_count = self.get_num_sfps()
252262
for index in range(sfp_count):
253-
sfp_module = SFP(index)
263+
if self.RJ45_port_list and index in self.RJ45_port_list:
264+
sfp_module = RJ45Port(index)
265+
else:
266+
sfp_module = SFP(index)
254267
self._sfp_list.append(sfp_module)
255268
self.sfp_initialized_count = sfp_count
256269
elif self.sfp_initialized_count != len(self._sfp_list):
257270
from .sfp import SFP
258271
for index in range(len(self._sfp_list)):
259272
if self._sfp_list[index] is None:
260-
self._sfp_list[index] = SFP(index)
273+
if self.RJ45_port_list and index in self.RJ45_port_list:
274+
self._sfp_list[index] = RJ45Port(index)
275+
else:
276+
self._sfp_list[index] = SFP(index)
261277
self.sfp_initialized_count = len(self._sfp_list)
262278

263279
def get_num_sfps(self):
@@ -324,7 +340,7 @@ def get_change_event(self, timeout=0):
324340
# Initialize SFP event first
325341
if not self.sfp_event:
326342
from .sfp_event import sfp_event
327-
self.sfp_event = sfp_event()
343+
self.sfp_event = sfp_event(self.RJ45_port_list)
328344
self.sfp_event.initialize()
329345

330346
wait_for_ever = (timeout == 0)
@@ -340,7 +356,8 @@ def get_change_event(self, timeout=0):
340356
status = self.sfp_event.check_sfp_status(port_dict, error_dict, timeout)
341357

342358
if status:
343-
self.reinit_sfps(port_dict)
359+
if port_dict:
360+
self.reinit_sfps(port_dict)
344361
result_dict = {'sfp':port_dict}
345362
if error_dict:
346363
result_dict['sfp_error'] = error_dict
@@ -515,8 +532,8 @@ def initialize_components(self):
515532
from .component import ComponentONIE, ComponentSSD, ComponentBIOS, ComponentCPLD
516533
self._component_list.append(ComponentONIE())
517534
self._component_list.append(ComponentSSD())
518-
self._component_list.append(ComponentBIOS())
519-
self._component_list.extend(ComponentCPLD.get_component_list())
535+
self._component_list.append(DeviceDataManager.get_bios_component())
536+
self._component_list.extend(DeviceDataManager.get_cpld_component_list())
520537

521538
def get_num_components(self):
522539
"""

platform/mellanox/mlnx-platform-api/sonic_platform/component.py

+66-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import glob
3030
import tempfile
3131
import subprocess
32+
from sonic_py_common import device_info
3233
if sys.version_info[0] > 2:
3334
import configparser
3435
else:
@@ -136,7 +137,17 @@ class ONIEUpdater(object):
136137

137138
ONIE_IMAGE_INFO_COMMAND = '/bin/bash {} -q -i'
138139

140+
# Upgrading fireware from ONIE is not supported from the beginning on some platforms, like SN2700.
141+
# There is a logic to check the ONIE version in order to know whether it is supported.
142+
# If it is not supported, we will not proceed and print some error message.
143+
# For SN2201, upgrading fireware from ONIE is supported from day one so we do not need to check it.
144+
PLATFORM_ALWAYS_SUPPORT_UPGRADE = ['x86_64-nvidia_sn2201-r0']
145+
139146
BIOS_UPDATE_FILE_EXT = '.rom'
147+
148+
149+
def __init__(self):
150+
self.platform = device_info.get_platform()
140151

141152
def __add_prefix(self, image_path):
142153
if self.BIOS_UPDATE_FILE_EXT not in image_path:
@@ -336,6 +347,9 @@ def update_firmware(self, image_path, allow_reboot=True):
336347
raise
337348

338349
def is_non_onie_firmware_update_supported(self):
350+
if self.platform in self.PLATFORM_ALWAYS_SUPPORT_UPGRADE:
351+
return True
352+
339353
current_version = self.get_onie_version()
340354
_, _, major1, minor1, release1, _ = self.parse_onie_version(current_version)
341355
version1 = int("{}{}{}".format(major1, minor1, release1))
@@ -698,6 +712,37 @@ def update_firmware(self, image_path):
698712
self.__install_firmware(image_path)
699713

700714

715+
class ComponentBIOSSN2201(Component):
716+
COMPONENT_NAME = 'BIOS'
717+
COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System'
718+
719+
BIOS_VERSION_COMMAND = 'dmidecode -t0'
720+
721+
def __init__(self):
722+
super(ComponentBIOSSN2201, self).__init__()
723+
724+
self.name = self.COMPONENT_NAME
725+
self.description = self.COMPONENT_DESCRIPTION
726+
727+
def get_firmware_version(self):
728+
cmd = self.BIOS_VERSION_COMMAND
729+
730+
try:
731+
output = subprocess.check_output(cmd.split(),
732+
stderr=subprocess.STDOUT,
733+
universal_newlines=True).rstrip('\n')
734+
except subprocess.CalledProcessError as e:
735+
raise RuntimeError("Failed to get {} version: {}".format(self.name, str(e)))
736+
737+
match = re.search('Version: (.*)', output)
738+
if match:
739+
version = match.group(1)
740+
else:
741+
version = 'Unknown version'
742+
743+
return version
744+
745+
701746
class ComponentCPLD(Component):
702747
COMPONENT_NAME = 'CPLD{}'
703748
COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device'
@@ -744,7 +789,7 @@ def __get_mst_device(self):
744789

745790
return mst_dev_list[0]
746791

747-
def __install_firmware(self, image_path):
792+
def _install_firmware(self, image_path):
748793
if not self._check_file_validity(image_path):
749794
return False
750795

@@ -830,9 +875,9 @@ def install_firmware(self, image_path):
830875
burn_firmware = mpfa.get_metadata().get('firmware', 'burn')
831876

832877
print("INFO: Processing {} burn file: firmware install".format(self.name))
833-
return self.__install_firmware(os.path.join(mpfa.get_path(), burn_firmware))
878+
return self._install_firmware(os.path.join(mpfa.get_path(), burn_firmware))
834879
else:
835-
return self.__install_firmware(image_path)
880+
return self._install_firmware(image_path)
836881

837882
def update_firmware(self, image_path):
838883
with MPFAManager(image_path) as mpfa:
@@ -845,11 +890,11 @@ def update_firmware(self, image_path):
845890
refresh_firmware = mpfa.get_metadata().get('firmware', 'refresh')
846891

847892
print("INFO: Processing {} burn file: firmware install".format(self.name))
848-
if not self.__install_firmware(os.path.join(mpfa.get_path(), burn_firmware)):
893+
if not self._install_firmware(os.path.join(mpfa.get_path(), burn_firmware)):
849894
return
850895

851896
print("INFO: Processing {} refresh file: firmware update".format(self.name))
852-
self.__install_firmware(os.path.join(mpfa.get_path(), refresh_firmware))
897+
self._install_firmware(os.path.join(mpfa.get_path(), refresh_firmware))
853898

854899
@classmethod
855900
def get_component_list(cls):
@@ -862,3 +907,19 @@ def get_component_list(cls):
862907
component_list.append(cls(cpld_idx))
863908

864909
return component_list
910+
911+
912+
class ComponentCPLDSN2201(ComponentCPLD):
913+
CPLD_FIRMWARE_UPDATE_COMMAND = 'cpldupdate --gpio {} --uncustomized --print-progress'
914+
915+
def _install_firmware(self, image_path):
916+
cmd = self.CPLD_FIRMWARE_UPDATE_COMMAND.format(image_path)
917+
918+
try:
919+
print("INFO: Installing {} firmware update: path={}".format(self.name, image_path))
920+
subprocess.check_call(cmd.split(), universal_newlines=True)
921+
except subprocess.CalledProcessError as e:
922+
print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e)))
923+
return False
924+
925+
return True

platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@
158158
'thermal': {
159159
"capability": {
160160
"comex_amb": False,
161-
"cpu_amb": True,
162-
"swb_amb": True
161+
"cpu_amb": True
163162
}
164163
}
165164
},
@@ -281,3 +280,21 @@ def get_cpu_thermal_threshold(cls):
281280
return None, None
282281

283282
return thermal_data.get('cpu_threshold', (None, None))
283+
284+
@classmethod
285+
def get_bios_component(cls):
286+
from .component import ComponentBIOS, ComponentBIOSSN2201
287+
if cls.get_platform_name() in ['x86_64-nvidia_sn2201-r0']:
288+
# For SN2201, special chass is required for handle BIOS
289+
# Currently, only fetching BIOS version is supported
290+
return ComponentBIOSSN2201()
291+
return ComponentBIOS()
292+
293+
@classmethod
294+
def get_cpld_component_list(cls):
295+
from .component import ComponentCPLD, ComponentCPLDSN2201
296+
if cls.get_platform_name() in ['x86_64-nvidia_sn2201-r0']:
297+
# For SN2201, special chass is required for handle BIOS
298+
# Currently, only fetching BIOS version is supported
299+
return ComponentCPLDSN2201.get_component_list()
300+
return ComponentCPLD.get_component_list()

0 commit comments

Comments
 (0)