Skip to content

Commit

Permalink
[SFP-Refactor] Implement CMIS Low Power mode (#237)
Browse files Browse the repository at this point in the history
* [SFP-Refactor] Implement CMIS LP mode
  • Loading branch information
aravindmani-1 committed Nov 29, 2021
1 parent 9cea07f commit cd69212
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 10 deletions.
4 changes: 2 additions & 2 deletions sonic_platform_base/sonic_xcvr/api/public/c_cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ def set_laser_freq(self, freq):
assert channel_number % 3 == 0
if channel_number > hi_ch_num or channel_number < low_ch_num:
raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.')
self.set_low_power(True)
self.set_lpmode(True)
time.sleep(5)
status = self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number)
time.sleep(1)
self.set_low_power(False)
self.set_lpmode(False)
time.sleep(1)
return status

Expand Down
36 changes: 31 additions & 5 deletions sonic_platform_base/sonic_xcvr/api/public/cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,15 +871,41 @@ def reset_module(self, reset = False):
else:
return True

def set_low_power(self, AssertLowPower):
def get_lpmode(self):
'''
Retrieves Low power module status
Returns True if module in low power else returns False.
'''
if self.is_flat_memory() or not self.get_lpmode_support():
return False

lpmode = self.xcvr_eeprom.read(consts.TRANS_MODULE_STATUS_FIELD)
if lpmode is not None:
if lpmode.get('ModuleState') == 'ModuleLowPwr':
return True
return False

def set_lpmode(self, lpmode):
'''
This function sets the module to low power state.
AssertLowPower being 0 means "set to high power"
AssertLowPower being 1 means "set to low power"
lpmode being False means "set to high power"
lpmode being True means "set to low power"
Return True if the provision succeeds, False if it fails
'''
low_power_control = AssertLowPower << 6
return self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control)

if self.is_flat_memory() or not self.get_lpmode_support():
return False

lpmode_val = self.xcvr_eeprom.read(consts.MODULE_LEVEL_CONTROL)
if lpmode_val is not None:
if lpmode is True:
lpmode_val = lpmode_val | (1 << 4)
else:
lpmode_val = lpmode_val & ~(1 << 4)
self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, lpmode_val)
time.sleep(0.1)
return self.get_lpmode()
return False

def get_loopback_capability(self):
'''
Expand Down
2 changes: 1 addition & 1 deletion sonic_platform_base/sonic_xcvr/fields/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@
LASER_TUNING_DETAIL = "TxTuningDetail"

# CONFIG
TRANS_CONFIG_FIELD = "TransceriverConfig"
TRANS_CONFIG_FIELD = "TransceiverConfig"
MODULE_LEVEL_CONTROL = "ModuleControl"

CTRLS_ADVT_FIELD = "Supported Controls Advertisement"
Expand Down
18 changes: 18 additions & 0 deletions sonic_platform_base/sonic_xcvr/sfp_optoe_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ def set_power_override(self, power_override, power_set):
def get_eeprom_path(self):
raise NotImplementedError

def get_lpmode(self):
"""
This common API is applicable only for CMIS as Low Power mode can be verified
using EEPROM registers.For other media types like QSFP28/QSFP+ etc., platform
vendors has to implement accordingly.
"""
api = self.get_xcvr_api()
return api.get_lpmode() if api is not None else None

def set_lpmode(self, lpmode):
"""
This common API is applicable only for CMIS as Low Power mode can be controlled
via EEPROM registers.For other media types like QSFP28/QSFP+ etc., platform
vendors has to implement accordingly.
"""
api = self.get_xcvr_api()
return api.set_lp_mode(lpmode) if api is not None else None

def read_eeprom(self, offset, num_bytes):
try:
with open(self.get_eeprom_path(), mode='rb', buffering=0) as f:
Expand Down
4 changes: 4 additions & 0 deletions tests/sonic_xcvr/test_ccmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ def test_get_supported_freq_config(self, mock_response, expected):
(195950, (0xff, -72, 120, 191300, 196100)),
])
def test_set_laser_freq(self, input_param, mock_response):
self.api.is_flat_memory = MagicMock()
self.api.is_flat_memory.return_value = False
self.api.get_lpmode_support = MagicMock()
self.api.get_lpmode_support.return_value = False
self.api.get_supported_freq_config = MagicMock()
self.api.get_supported_freq_config.return_value = mock_response
self.api.set_laser_freq(input_param)
Expand Down
8 changes: 6 additions & 2 deletions tests/sonic_xcvr/test_cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,8 +747,12 @@ def test_get_supported_power_config(self, mock_response, expected):
def test_reset_module(self):
self.api.reset_module(True)

def test_set_low_power(self, ):
self.api.set_low_power(True)
def test_set_low_power(self):
self.api.is_flat_memory = MagicMock()
self.api.is_flat_memory.return_value = False
self.api.get_lpmode_support = MagicMock()
self.api.get_lpmode_support.return_value = False
self.api.set_lpmode(True)

@pytest.mark.parametrize("mock_response, expected", [
(127,
Expand Down

0 comments on commit cd69212

Please sign in to comment.