[Mellanox] [202106] Fix issue: SFP might not be re-initialized after cable plug in (#9387)

- Why I did it
Fix issue: SFP might not be re-initialized after cable plug in. There could be case like:
1. The SFP object was initialized as QSFP type
2. User use adapter to connect a SFP to a QSFP port
3. The SFP object treat the SFP as QSFP and failed to process EEPROM

- How I did it
If a new SFP is plugged, always re-initialize the SFP

- How to verify it
Added unit test case
This commit is contained in:
Junchao-Mellanox 2021-12-14 22:27:26 +08:00 committed by GitHub
parent 3ae3eeda35
commit 73a17d8876
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 13 deletions

View File

@ -84,7 +84,7 @@ class Chassis(ChassisBase):
# Initialize DMI data # Initialize DMI data
self.dmi_data = None self.dmi_data = None
# move the initialization of each components to their dedicated initializer # move the initialization of each components to their dedicated initializer
# which will be called from platform # which will be called from platform
# #
@ -261,7 +261,7 @@ class Chassis(ChassisBase):
def get_revision(self): def get_revision(self):
""" """
Retrieves the hardware revision of the device Retrieves the hardware revision of the device
Returns: Returns:
string: Revision value of device string: Revision value of device
""" """
@ -269,7 +269,7 @@ class Chassis(ChassisBase):
self.dmi_data = self._parse_dmi(DMI_FILE) self.dmi_data = self._parse_dmi(DMI_FILE)
return self.dmi_data.get(DMI_VERSION, "N/A") return self.dmi_data.get(DMI_VERSION, "N/A")
############################################## ##############################################
# SFP methods # SFP methods
############################################## ##############################################
@ -290,7 +290,7 @@ class Chassis(ChassisBase):
Retrieves all sfps available on this chassis Retrieves all sfps available on this chassis
Returns: Returns:
A list of objects derived from SfpBase representing all sfps A list of objects derived from SfpBase representing all sfps
available on this chassis available on this chassis
""" """
if not self.sfp_module_full_initialized: if not self.sfp_module_full_initialized:
@ -361,7 +361,7 @@ class Chassis(ChassisBase):
Note: Note:
We overload this method to ensure that watchdog is only initialized We overload this method to ensure that watchdog is only initialized
when it is referenced. Currently, only one daemon can open the watchdog. when it is referenced. Currently, only one daemon can open the watchdog.
To initialize watchdog in the constructor causes multiple daemon To initialize watchdog in the constructor causes multiple daemon
try opening watchdog when loading and constructing a chassis object try opening watchdog when loading and constructing a chassis object
and fail. By doing so we can eliminate that risk. and fail. By doing so we can eliminate that risk.
""" """
@ -450,7 +450,7 @@ class Chassis(ChassisBase):
def _verify_reboot_cause(self, filename): def _verify_reboot_cause(self, filename):
''' '''
Open and read the reboot cause file in Open and read the reboot cause file in
/var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT) /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT)
If a reboot cause file doesn't exists, returns '0'. If a reboot cause file doesn't exists, returns '0'.
''' '''
@ -550,7 +550,7 @@ class Chassis(ChassisBase):
- True if call successful, False if not; - True if call successful, False if not;
- A nested dictionary where key is a device type, - A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the format of value is a dictionary with key:value pairs in the format of
{'device_id':'device_event'}, {'device_id':'device_event'},
where device_id is the device ID for this device and where device_id is the device ID for this device and
device_event, device_event,
status='1' represents device inserted, status='1' represents device inserted,
@ -594,10 +594,6 @@ class Chassis(ChassisBase):
:param port_dict: SFP event data :param port_dict: SFP event data
:return: :return:
""" """
# SFP not initialize yet, do nothing
if not self.sfp_module_full_initialized:
return
from . import sfp from . import sfp
for index, status in port_dict.items(): for index, status in port_dict.items():
if status == sfp.SFP_STATUS_INSERTED: if status == sfp.SFP_STATUS_INSERTED:

View File

@ -1,7 +1,7 @@
import os import os
import sys import sys
import pytest import pytest
from mock import MagicMock from mock import MagicMock, patch
from .mock_platform import MockFan from .mock_platform import MockFan
test_path = os.path.dirname(os.path.abspath(__file__)) test_path = os.path.dirname(os.path.abspath(__file__))
@ -11,7 +11,7 @@ sys.path.insert(0, modules_path)
os.environ["PLATFORM_API_UNIT_TESTING"] = "1" os.environ["PLATFORM_API_UNIT_TESTING"] = "1"
from sonic_py_common import device_info from sonic_py_common import device_info
from sonic_platform.sfp import SFP, SX_PORT_MODULE_STATUS_INITIALIZING, SX_PORT_MODULE_STATUS_PLUGGED, SX_PORT_MODULE_STATUS_UNPLUGGED, SX_PORT_MODULE_STATUS_PLUGGED_WITH_ERROR, SX_PORT_MODULE_STATUS_PLUGGED_DISABLED from sonic_platform.sfp import SFP, SX_PORT_MODULE_STATUS_INITIALIZING, SX_PORT_MODULE_STATUS_PLUGGED, SX_PORT_MODULE_STATUS_UNPLUGGED, SX_PORT_MODULE_STATUS_PLUGGED_WITH_ERROR, SX_PORT_MODULE_STATUS_PLUGGED_DISABLED, SFP_STATUS_INSERTED
from sonic_platform.chassis import Chassis from sonic_platform.chassis import Chassis
@ -123,3 +123,16 @@ def test_sfp_get_error_status():
description = sfp.get_error_description() description = sfp.get_error_description()
assert description == expected_description assert description == expected_description
@patch('sonic_platform.sfp.SFP.reinit')
def test_reinit_sfps(mock_reinit_sfps):
port_dict = {}
chassis = Chassis()
chassis.reinit_sfps(port_dict)
assert not mock_reinit_sfps.called
port_dict = {1: SFP_STATUS_INSERTED}
chassis.reinit_sfps(port_dict)
assert mock_reinit_sfps.called
assert chassis._sfp_list[0] is not None