Skip to content

Commit c1f317d

Browse files
authored
Gracefully handle CMIS APIs for passive modules (#238)
* Gracefully handle CMIS APIs for passive modules Signed-off-by: Prince George <[email protected]> * Address review comments Signed-off-by: Prince George <[email protected]> * Fix sfputil show eeprom for AOC * Address review comment * fix crash * Fix comments
1 parent ec7335d commit c1f317d

File tree

4 files changed

+128
-126
lines changed

4 files changed

+128
-126
lines changed

sonic_platform_base/sonic_xcvr/api/public/cmis.py

+78-40
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_model(self):
3232

3333
def get_vendor_rev(self):
3434
'''
35-
This function returns the revision level for part number provided by vendor
35+
This function returns the revision level for part number provided by vendor
3636
'''
3737
return self.xcvr_eeprom.read(consts.VENDOR_REV_FIELD)
3838

@@ -58,6 +58,8 @@ def get_module_hardware_revision(self):
5858
'''
5959
This function returns the module hardware revision
6060
'''
61+
if self.is_flat_memory():
62+
return '0.0'
6163
hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV)
6264
hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV)
6365
hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]]
@@ -98,6 +100,8 @@ def get_module_inactive_firmware(self):
98100
'''
99101
This function returns the inactive firmware version
100102
'''
103+
if self.is_flat_memory():
104+
return 'N/A'
101105
inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV)
102106
inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV)
103107
inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]]
@@ -115,7 +119,7 @@ def get_transceiver_info(self):
115119
xcvr_info = {
116120
"type": admin_info[consts.ID_FIELD],
117121
"type_abbrv_name": admin_info[consts.ID_ABBRV_FIELD],
118-
"hardware_rev": '.'.join([str(admin_info[consts.HW_MAJOR_REV]),str(admin_info[consts.HW_MINOR_REV])]),
122+
"hardware_rev": self.get_module_hardware_revision(),
119123
"serial": admin_info[consts.VENDOR_SERIAL_NO_FIELD],
120124
"manufacturer": admin_info[consts.VENDOR_NAME_FIELD],
121125
"model": admin_info[consts.VENDOR_PART_NO_FIELD],
@@ -139,15 +143,9 @@ def get_transceiver_info(self):
139143
xcvr_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option()
140144
xcvr_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option()
141145
apsel_dict = self.get_active_apsel_hostlane()
142-
xcvr_info['active_apsel_hostlane1'] = apsel_dict['ActiveAppSelLane1']
143-
xcvr_info['active_apsel_hostlane2'] = apsel_dict['ActiveAppSelLane2']
144-
xcvr_info['active_apsel_hostlane3'] = apsel_dict['ActiveAppSelLane3']
145-
xcvr_info['active_apsel_hostlane4'] = apsel_dict['ActiveAppSelLane4']
146-
xcvr_info['active_apsel_hostlane5'] = apsel_dict['ActiveAppSelLane5']
147-
xcvr_info['active_apsel_hostlane6'] = apsel_dict['ActiveAppSelLane6']
148-
xcvr_info['active_apsel_hostlane7'] = apsel_dict['ActiveAppSelLane7']
149-
xcvr_info['active_apsel_hostlane8'] = apsel_dict['ActiveAppSelLane8']
150-
146+
for lane in range(1, self.NUM_CHANNELS+1):
147+
xcvr_info["%s%d" % ("active_apsel_hostlane", lane)] = \
148+
apsel_dict["%s%d" % (consts.ACTIVE_APSEL_HOSTLANE, lane)]
151149
xcvr_info['media_interface_technology'] = self.get_media_interface_technology()
152150
xcvr_info['vendor_rev'] = self.get_vendor_rev()
153151
xcvr_info['cmis_rev'] = self.get_cmis_rev()
@@ -188,9 +186,9 @@ def get_transceiver_bulk_status(self):
188186
}
189187

190188
for i in range(1, self.NUM_CHANNELS + 1):
191-
bulk_status["tx%dbias" % i] = tx_bias['LaserBiasTx%dField' % i]
192-
bulk_status["rx%dpower" % i] = rx_power['OpticalPowerRx%dField' %i]
193-
bulk_status["tx%dpower" % i] = tx_power['OpticalPowerTx%dField' %i]
189+
bulk_status["tx%dbias" % i] = tx_bias[i - 1]
190+
bulk_status["rx%dpower" % i] = rx_power[i - 1]
191+
bulk_status["tx%dpower" % i] = tx_power[i - 1]
194192

195193
laser_temp_dict = self.get_laser_temperature()
196194
bulk_status['laser_temperature'] = laser_temp_dict['monitor value']
@@ -257,7 +255,7 @@ def get_transceiver_threshold_info(self):
257255
threshold_info_dict['prefecberhighalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][1]
258256
threshold_info_dict['prefecberlowalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][2]
259257
threshold_info_dict['prefecberhighwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][3]
260-
threshold_info_dict['prefecberlowwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][4]
258+
threshold_info_dict['prefecberlowwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][4]
261259
threshold_info_dict['postfecberhighalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][1]
262260
threshold_info_dict['postfecberlowalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][2]
263261
threshold_info_dict['postfecberhighwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][3]
@@ -459,9 +457,13 @@ def get_tx_bias(self):
459457
tx_bias_support = self.get_tx_bias_support()
460458
if tx_bias_support is None:
461459
return None
462-
if not tx_bias_support:
463-
return ["N/A" for _ in range(self.NUM_CHANNELS)]
464-
tx_bias = self.xcvr_eeprom.read(consts.TX_BIAS_FIELD)
460+
tx_bias = ["N/A" for _ in range(self.NUM_CHANNELS)]
461+
462+
if tx_bias_support:
463+
tx_bias = self.xcvr_eeprom.read(consts.TX_BIAS_FIELD)
464+
if tx_bias is not None:
465+
tx_bias = [tx_bias['LaserBiasTx%dField' % i] for i in range(1, self.NUM_CHANNELS+1)]
466+
465467
return tx_bias
466468

467469
def get_tx_power(self):
@@ -471,9 +473,14 @@ def get_tx_power(self):
471473
tx_power_support = self.get_tx_power_support()
472474
if tx_power_support is None:
473475
return None
474-
if not tx_power_support:
475-
return ["N/A" for _ in range(self.NUM_CHANNELS)]
476-
tx_power = self.xcvr_eeprom.read(consts.TX_POWER_FIELD)
476+
477+
tx_power = ["N/A" for _ in range(self.NUM_CHANNELS)]
478+
479+
if tx_power_support:
480+
tx_power = self.xcvr_eeprom.read(consts.TX_POWER_FIELD)
481+
if tx_power is not None:
482+
tx_power = [tx_power['OpticalPowerTx%dField' %i] for i in range(1, self.NUM_CHANNELS+1)]
483+
477484
return tx_power
478485

479486
def get_tx_power_support(self):
@@ -486,9 +493,14 @@ def get_rx_power(self):
486493
rx_power_support = self.get_rx_power_support()
487494
if rx_power_support is None:
488495
return None
489-
if not rx_power_support:
490-
return ["N/A" for _ in range(self.NUM_CHANNELS)]
491-
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
496+
497+
rx_power = ["N/A" for _ in range(self.NUM_CHANNELS)]
498+
499+
if rx_power_support:
500+
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
501+
if rx_power is not None:
502+
rx_power = [rx_power['OpticalPowerRx%dField' %i] for i in range(1, self.NUM_CHANNELS+1)]
503+
492504
return rx_power
493505

494506
def get_rx_power_support(self):
@@ -596,6 +608,8 @@ def get_module_media_type(self):
596608
'''
597609
This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T.
598610
'''
611+
if self.is_flat_memory():
612+
return 'N/A'
599613
return self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD)
600614

601615
def get_host_electrical_interface(self):
@@ -608,6 +622,9 @@ def get_module_media_interface(self):
608622
'''
609623
This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6
610624
'''
625+
if self.is_flat_memory():
626+
return 'N/A'
627+
611628
media_type = self.get_module_media_type()
612629
if media_type == 'Multimode Fiber (MMF)':
613630
return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM)
@@ -631,15 +648,16 @@ def is_coherent_module(self):
631648

632649
def get_host_lane_count(self):
633650
'''
634-
This function returns number of host lanes
651+
This function returns number of host lanes for default application
635652
'''
636653
return self.xcvr_eeprom.read(consts.HOST_LANE_COUNT)
637654

638-
639655
def get_media_lane_count(self):
640656
'''
641-
This function returns number of media lanes
657+
This function returns number of media lanes for default application
642658
'''
659+
if self.is_flat_memory():
660+
return 0
643661
return self.xcvr_eeprom.read(consts.MEDIA_LANE_COUNT)
644662

645663
def get_media_interface_technology(self):
@@ -658,13 +676,21 @@ def get_media_lane_assignment_option(self):
658676
'''
659677
This function returns the media lane that the application is allowed to begin on
660678
'''
679+
if self.is_flat_memory():
680+
return 'N/A'
661681
return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION)
662682

663683
def get_active_apsel_hostlane(self):
664684
'''
665685
This function returns the application select code that each host lane has
666686
'''
667-
return self.xcvr_eeprom.read(consts.ACTIVE_APSEL_CODE)
687+
apsel_dict = {}
688+
if self.is_flat_memory():
689+
for lane in range(1, self.NUM_CHANNELS+1):
690+
apsel_dict["%s%d" % (consts.ACTIVE_APSEL_HOSTLANE, lane)] = 'N/A'
691+
else:
692+
apsel_dict = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_CODE)
693+
return apsel_dict
668694

669695
def get_tx_config_power(self):
670696
'''
@@ -730,6 +756,17 @@ def get_laser_temperature(self):
730756
'''
731757
This function returns the laser temperature monitor value
732758
'''
759+
laser_temp_dict = {
760+
'monitor value' : 'N/A',
761+
'high alarm' : 'N/A',
762+
'low alarm' : 'N/A',
763+
'high warn' : 'N/A',
764+
'low warn' : 'N/A'
765+
}
766+
767+
if self.is_flat_memory():
768+
return laser_temp_dict
769+
733770
try:
734771
aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type()
735772
except TypeError:
@@ -748,7 +785,8 @@ def get_laser_temperature(self):
748785
laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE
749786
laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE
750787
else:
751-
return None
788+
return laser_temp_dict
789+
752790
laser_temp_dict = {'monitor value': laser_temp,
753791
'high alarm': laser_temp_high_alarm,
754792
'low alarm': laser_temp_low_alarm,
@@ -913,7 +951,7 @@ def get_vdm(self):
913951
self.vdm
914952
except AttributeError:
915953
self.get_vdm_api()
916-
vdm = self.vdm.get_vdm_allpage()
954+
vdm = self.vdm.get_vdm_allpage() if not self.is_flat_memory() else {}
917955
return vdm
918956

919957
def get_module_firmware_fault_state_changed(self):
@@ -1100,7 +1138,7 @@ def get_module_fw_info(self):
11001138
else:
11011139
ImageA = "N/A"
11021140
txt += 'Image A Version: %s\n' %ImageA
1103-
1141+
11041142
if ImageBValid == 0:
11051143
# Registers 9Fh:174,175; 176.177
11061144
ImageB = '%d.%d.%d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41]))
@@ -1119,7 +1157,7 @@ def get_module_fw_info(self):
11191157
elif ImageBCommitted == 1:
11201158
CommittedImage = 'B'
11211159
else:
1122-
CommittedImage = 'N/A'
1160+
CommittedImage = 'N/A'
11231161
txt += 'Running Image: %s; Committed Image: %s\n' %(RunningImage, CommittedImage)
11241162
else:
11251163
txt += 'Reply payload check code error\n'
@@ -1142,8 +1180,8 @@ def module_fw_run(self, mode = 0x01):
11421180
02h = Traffic affecting Reset to Running Image.
11431181
03h = Attempt Hitless Reset to Running Image
11441182
1145-
This function returns True if firmware run successfully completes.
1146-
Otherwise it will return False.
1183+
This function returns True if firmware run successfully completes.
1184+
Otherwise it will return False.
11471185
"""
11481186
try:
11491187
self.cdb
@@ -1177,8 +1215,8 @@ def module_fw_commit(self):
11771215
The host uses this command to commit the running image
11781216
so that the module will boot from it on future boots.
11791217
1180-
This function returns True if firmware commit successfully completes.
1181-
Otherwise it will return False.
1218+
This function returns True if firmware commit successfully completes.
1219+
Otherwise it will return False.
11821220
"""
11831221
try:
11841222
self.cdb
@@ -1327,7 +1365,7 @@ def module_fw_upgrade(self, imagepath):
13271365
imagepath specifies where firmware image file is located.
13281366
target_firmware is a string that specifies the firmware version to upgrade to
13291367
1330-
This function returns True if download successfully completes.
1368+
This function returns True if download successfully completes.
13311369
Otherwise it will return False.
13321370
"""
13331371
result = self.get_module_fw_info()
@@ -1336,7 +1374,7 @@ def module_fw_upgrade(self, imagepath):
13361374
except (ValueError, TypeError):
13371375
return result['status'], result['info']
13381376
result = self.get_module_fw_upgrade_feature()
1339-
try:
1377+
try:
13401378
startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = result['result']
13411379
except (ValueError, TypeError):
13421380
return result['status'], result['info']
@@ -1351,7 +1389,7 @@ def module_fw_upgrade(self, imagepath):
13511389
def module_fw_switch(self):
13521390
"""
13531391
This function switch the active/inactive module firmware in the current module memory
1354-
This function returns True if firmware switch successfully completes.
1392+
This function returns True if firmware switch successfully completes.
13551393
Otherwise it will return False.
13561394
If not both images are valid, it will stop firmware switch and return False
13571395
"""
@@ -1572,7 +1610,7 @@ def get_transceiver_status(self):
15721610
trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag']
15731611
trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag']
15741612
trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag']
1575-
try:
1613+
try:
15761614
aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type()
15771615
if aux2_mon_type == 0:
15781616
trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag']

sonic_platform_base/sonic_xcvr/fields/consts.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
RX_PWR_1_FIELD = "Rx_PWR(1)"
125125
RX_PWR_0_FIELD = "Rx_PWR(0)"
126126
TX_I_SLOPE_FIELD = "Tx_I(Slope)"
127-
TX_I_OFFSET_FIELD = "Tx_I(Offset)"
127+
TX_I_OFFSET_FIELD = "Tx_I(Offset)"
128128
TX_PWR_SLOPE_FIELD = "Tx_PWR(Slope)"
129129
TX_PWR_OFFSET_FIELD = "Tx_PWR(Offset)"
130130
T_SLOPE_FIELD = "T (Slope)"
@@ -143,6 +143,7 @@
143143
# CMIS
144144

145145
ADMIN_INFO_FIELD = "AdminInfo"
146+
ADVERTISING_FIELD = "Advertising"
146147
MEDIA_TYPE_FIELD = "ModuleMediaType"
147148
HOST_ELECTRICAL_INTERFACE = "HostElectricalInterfaceID"
148149
MODULE_MEDIA_INTERFACE_850NM = "ModuleMediaInterface850nm"

sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ def __init__(self, codes):
2727
)
2828
)
2929

30+
# Should contain ONLY Lower page fields
3031
self.ADMIN_INFO = RegGroupField(consts.ADMIN_INFO_FIELD,
31-
CodeRegField(consts.ID_FIELD, self.getaddr(0x0, 128), self.codes.XCVR_IDENTIFIERS),
32+
CodeRegField(consts.ID_FIELD, self.getaddr(0x0, 0), self.codes.XCVR_IDENTIFIERS),
3233
CodeRegField(consts.ID_ABBRV_FIELD, self.getaddr(0x0, 128), self.codes.XCVR_IDENTIFIER_ABBRV),
3334
StringRegField(consts.VENDOR_NAME_FIELD, self.getaddr(0x0, 129), size=16),
3435
HexRegField(consts.VENDOR_OUI_FIELD, self.getaddr(0x0, 145), size=3),
@@ -57,17 +58,14 @@ def __init__(self, codes):
5758
CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, self.getaddr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE),
5859
CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, self.getaddr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE),
5960
CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, self.getaddr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE),
60-
NumberRegField(consts.MEDIA_LANE_COUNT, self.getaddr(0x0, 88),
61+
NumberRegField(consts.MEDIA_LANE_COUNT, self.getaddr(0x0, 88),
6162
*(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4))
6263
),
63-
NumberRegField(consts.HOST_LANE_COUNT, self.getaddr(0x0, 88),
64+
NumberRegField(consts.HOST_LANE_COUNT, self.getaddr(0x0, 88),
6465
*(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8))
6566
),
6667
NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, self.getaddr(0x0, 89), format="B", size=1),
67-
NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, self.getaddr(0x1, 176), format="B", size=1),
6868
CodeRegField(consts.MEDIA_INTERFACE_TECH, self.getaddr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH),
69-
NumberRegField(consts.HW_MAJOR_REV, self.getaddr(0x1, 130), size=1),
70-
NumberRegField(consts.HW_MINOR_REV, self.getaddr(0x1, 131), size=1),
7169
NumberRegField(consts.CMIS_MAJOR_REVISION, self.getaddr(0x0, 1),
7270
*(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8))
7371
),
@@ -76,6 +74,13 @@ def __init__(self, codes):
7674
),
7775
NumberRegField(consts.ACTIVE_FW_MAJOR_REV, self.getaddr(0x0, 39), format="B", size=1),
7876
NumberRegField(consts.ACTIVE_FW_MINOR_REV, self.getaddr(0x0, 40), format="B", size=1),
77+
)
78+
79+
# Should contain ONLY upper page fields
80+
self.ADVERTISING = RegGroupField(consts.ADVERTISING_FIELD,
81+
NumberRegField(consts.HW_MAJOR_REV, self.getaddr(0x1, 130), size=1),
82+
NumberRegField(consts.HW_MINOR_REV, self.getaddr(0x1, 131), size=1),
83+
NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, self.getaddr(0x1, 176), format="B", size=1),
7984
NumberRegField(consts.INACTIVE_FW_MAJOR_REV, self.getaddr(0x1, 128), format="B", size=1),
8085
NumberRegField(consts.INACTIVE_FW_MINOR_REV, self.getaddr(0x1, 129), format="B", size=1),
8186

0 commit comments

Comments
 (0)