@@ -17,6 +17,7 @@ class MockSxFd(object):
1717 new_sx_fd_t_p = MagicMock (return_value = MockSxFd ())
1818 new_sx_user_channel_t_p = MagicMock ()
1919from sonic_py_common .logger import Logger
20+ from .sfp import SFP
2021
2122# SFP status from PMAOS register
2223# 0x1 plug in
@@ -30,16 +31,6 @@ class MockSxFd(object):
3031SDK_SFP_STATE_ERR = 0x3
3132SDK_SFP_STATE_DIS = 0x4
3233
33- # SFP status that will be handled by XCVRD
34- STATUS_PLUGIN = '1' # 00000001
35- STATUS_PLUGOUT = '0' # 00000000
36- # SFP error status always come with STATUS_PLUGIN, so the last bit is always 1
37- STATUS_ERR_I2C_STUCK = '3' # 00000011
38- STATUS_ERR_BAD_EEPROM = '5' # 00000101
39- STATUS_ERR_UNSUPPORTED_CABLE = '9' # 00001001
40- STATUS_ERR_HIGH_TEMP = '17' # 00010001
41- STATUS_ERR_BAD_CABLE = '33' # 00100001
42-
4334# SFP status used in this file only, will not expose to XCVRD
4435# STATUS_ERROR will be mapped to different status according to the error code
4536STATUS_UNKNOWN = '-1'
@@ -69,19 +60,39 @@ class MockSxFd(object):
6960'''
7061
7162# SFP errors that will block eeprom accessing
72- sdk_sfp_err_type_dict = {
73- 0x2 : STATUS_ERR_I2C_STUCK ,
74- 0x3 : STATUS_ERR_BAD_EEPROM ,
75- 0x5 : STATUS_ERR_UNSUPPORTED_CABLE ,
76- 0x6 : STATUS_ERR_HIGH_TEMP ,
77- 0x7 : STATUS_ERR_BAD_CABLE
63+ SDK_SFP_BLOCKING_ERRORS = [
64+ 0x2 , # SFP.SFP_ERROR_BIT_I2C_STUCK,
65+ 0x3 , # SFP.SFP_ERROR_BIT_BAD_EEPROM,
66+ 0x5 , # SFP.SFP_ERROR_BIT_UNSUPPORTED_CABLE,
67+ 0x6 , # SFP.SFP_ERROR_BIT_HIGH_TEMP,
68+ 0x7 , # SFP.SFP_ERROR_BIT_BAD_CABLE
69+ ]
70+
71+ SDK_ERRORS_TO_ERROR_BITS = {
72+ 0x0 : SFP .SFP_ERROR_BIT_POWER_BUDGET_EXCEEDED ,
73+ 0x1 : SFP .SFP_MLNX_ERROR_BIT_LONGRANGE_NON_MLNX_CABLE ,
74+ 0x2 : SFP .SFP_ERROR_BIT_I2C_STUCK ,
75+ 0x3 : SFP .SFP_ERROR_BIT_BAD_EEPROM ,
76+ 0x4 : SFP .SFP_MLNX_ERROR_BIT_ENFORCE_PART_NUMBER_LIST ,
77+ 0x5 : SFP .SFP_ERROR_BIT_UNSUPPORTED_CABLE ,
78+ 0x6 : SFP .SFP_ERROR_BIT_HIGH_TEMP ,
79+ 0x7 : SFP .SFP_ERROR_BIT_BAD_CABLE ,
80+ 0x8 : SFP .SFP_MLNX_ERROR_BIT_PMD_TYPE_NOT_ENABLED ,
81+ 0xc : SFP .SFP_MLNX_ERROR_BIT_PCIE_POWER_SLOT_EXCEEDED
82+ }
83+
84+ SDK_ERRORS_TO_DESCRIPTION = {
85+ 0x1 : SFP .SFP_MLNX_ERROR_DESCRIPTION_LONGRANGE_NON_MLNX_CABLE ,
86+ 0x4 : SFP .SFP_MLNX_ERROR_DESCRIPTION_ENFORCE_PART_NUMBER_LIST ,
87+ 0x8 : SFP .SFP_MLNX_ERROR_DESCRIPTION_PMD_TYPE_NOT_ENABLED ,
88+ 0xc : SFP .SFP_MLNX_ERROR_DESCRIPTION_PCIE_POWER_SLOT_EXCEEDED
7889}
7990
8091sfp_value_status_dict = {
81- SDK_SFP_STATE_IN : STATUS_PLUGIN ,
82- SDK_SFP_STATE_OUT : STATUS_PLUGOUT ,
92+ SDK_SFP_STATE_IN : str ( SFP . SFP_STATUS_BIT_INSERTED ) ,
93+ SDK_SFP_STATE_OUT : str ( SFP . SFP_STATUS_BIT_REMOVED ) ,
8394 SDK_SFP_STATE_ERR : STATUS_ERROR ,
84- SDK_SFP_STATE_DIS : STATUS_PLUGOUT ,
95+ SDK_SFP_STATE_DIS : str ( SFP . SFP_STATUS_BIT_REMOVED ) ,
8596}
8697
8798# system level event/error
@@ -204,7 +215,7 @@ def deinitialize(self):
204215 delete_sx_fd_t_p (self .rx_fd_p )
205216 delete_sx_user_channel_t_p (self .user_channel_p )
206217
207- def check_sfp_status (self , port_change , timeout ):
218+ def check_sfp_status (self , port_change , error_dict , timeout ):
208219 """
209220 the meaning of timeout is aligned with select.select, which has the following meaning:
210221 0: poll, returns without blocked
@@ -242,6 +253,7 @@ def check_sfp_status(self, port_change, timeout):
242253 break
243254
244255 sfp_state = sfp_value_status_dict .get (module_state , STATUS_UNKNOWN )
256+ error_description = None
245257 if sfp_state == STATUS_UNKNOWN :
246258 # in the following sequence, STATUS_UNKNOWN can be returned.
247259 # so we shouldn't raise exception here.
@@ -256,18 +268,29 @@ def check_sfp_status(self, port_change, timeout):
256268
257269 # If get SFP status error(0x3) from SDK, then need to read the error_type to get the detailed error
258270 if sfp_state == STATUS_ERROR :
259- if error_type in sdk_sfp_err_type_dict .keys ():
260- # In SFP at error status case, need to overwrite the sfp_state with the exact error code
261- sfp_state = sdk_sfp_err_type_dict [error_type ]
262- else :
263- # For errors don't block the eeprom accessing, we don't report it to XCVRD
264- logger .log_info ("SFP error on port but not blocking eeprom read, error_type {}" .format (error_type ))
265- found += 1
271+ sfp_state_bits = SDK_ERRORS_TO_ERROR_BITS .get (error_type )
272+ if sfp_state_bits is None :
273+ logger .log_error ("Unrecognized error {} detected on ports {}" .format (error_type , port_list ))
274+ found += 1
266275 continue
267276
277+ if error_type in SDK_SFP_BLOCKING_ERRORS :
278+ # In SFP at error status case, need to overwrite the sfp_state with the exact error code
279+ sfp_state_bits |= SFP .SFP_ERROR_BIT_BLOCKING
280+
281+ # An error should be always set along with 'INSERTED'
282+ sfp_state_bits |= SFP .SFP_STATUS_BIT_INSERTED
283+
284+ # For vendor specific errors, the description should be returned as well
285+ error_description = SDK_ERRORS_TO_DESCRIPTION .get (error_type )
286+
287+ sfp_state = str (sfp_state_bits )
288+
268289 for port in port_list :
269290 logger .log_info ("SFP on port {} state {}" .format (port , sfp_state ))
270291 port_change [port + 1 ] = sfp_state
292+ if error_description :
293+ error_dict [port + 1 ] = error_description
271294 found += 1
272295
273296 return found != 0
0 commit comments