diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index 65acbc274..aa8a6cbff 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -88,9 +88,15 @@ def get_laser_config_freq(self): ''' freq_grid = self.get_freq_grid() channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + # OIF-CMIS 5.3 Table 8-66: 75GHz is 193.1 + n x 0.025 THz, but 150GHz + # is 193.1 + (n+3) x 0.025 THz - the two grids are not interchangeable. if freq_grid == 75: - config_freq = 193100 + channel * freq_grid/3 + config_freq = 193100 + channel * 25 + elif freq_grid == 150: + config_freq = 193100 + (channel + 3) * 25 else: + # All other grids (100/50/25/12.5/6.25/3.125GHz) use a plain + # 193.1 + n x grid formula with no additive offset. config_freq = 193100 + channel * freq_grid return config_freq @@ -154,7 +160,7 @@ def set_laser_freq(self, freq, grid): ''' This function sets the laser frequency. Unit in GHz ZR application will not support fine tuning of the laser - SONiC will only support 75 GHz and 100GHz frequency grids + SONiC will support 75 GHz, 100GHz and 150GHz frequency grids Return True if the provision succeeds, False if it fails ''' grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() @@ -169,6 +175,13 @@ def set_laser_freq(self, freq, grid): assert grid_supported_100GHz freq_grid = 0x50 channel_number = int(round((freq - 193100)/100)) + elif grid == 150: + freq_grid = 0x80 + # OIF-CMIS 5.3 Table 8-66: Frequency (THz) = 193.1 + (n+3) x 0.025, + # so n = (freq - 193100) / 25 - 3, and n (not n+3) must be a + # multiple of 6. + channel_number = int(round((freq - 193100)/25)) - 3 + assert channel_number % 6 == 0 else: return False self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index 53a996c65..ba8cd0482 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -5,6 +5,7 @@ from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis.c_cmis import CCmisMemMap from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom from sonic_platform_base.sonic_xcvr.codes.public.cmis import CmisCodes +from sonic_platform_base.sonic_xcvr.fields import consts class TestCCmis(object): @@ -39,6 +40,11 @@ def test_get_freq_grid(self, mock_response, expected): (75, 12, 193400), (75, -30, 192350), (100, 10, 194100), + # OIF-CMIS 5.3 Table 8-66: 150GHz grid is 193.1 + (n+3) x 0.025 THz, + # a +75GHz offset from the naive 193.1 + n x 0.025 used for 75GHz. + (150, 12, 193475), + (150, 0, 193175), + (150, -3, 193100), ]) def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): self.api.get_freq_grid = MagicMock() @@ -98,6 +104,10 @@ def test_get_supported_freq_config(self, mock_response, expected): @pytest.mark.parametrize("input_param, mock_response",[ ((193100,75), (0xff, -72, 120, 191300, 196100)), ((195950,100), (0xff, -72, 120, 191300, 196100)), + # 193475 is a valid 150GHz-grid point post-offset-fix (n=12); see + # test_set_laser_freq_150ghz_channel_offset for the exact channel + # number written. + ((193475,150), (0xff, -72, 120, 191300, 196100)), ]) def test_set_laser_freq(self, input_param, mock_response): self.api.is_flat_memory = MagicMock() @@ -108,6 +118,18 @@ def test_set_laser_freq(self, input_param, mock_response): self.api.get_supported_freq_config.return_value = mock_response self.api.set_laser_freq(input_param[0], input_param[1]) + def test_set_laser_freq_150ghz_channel_offset(self): + # OIF-CMIS 5.3 Table 8-66: Frequency = 193.1 + (n+3) x 0.025 THz for + # the 150GHz grid, so the channel number written must be 3 less than + # the naive (freq-193100)/25 used for the 75GHz grid. + self.api.is_flat_memory = MagicMock(return_value=False) + self.api.get_lpmode_support = MagicMock(return_value=False) + self.api.get_supported_freq_config = MagicMock( + return_value=(0xff, -72, 120, 191300, 196100)) + self.api.xcvr_eeprom.write = MagicMock(return_value=True) + self.api.set_laser_freq(193475, 150) + self.api.xcvr_eeprom.write.assert_any_call(consts.LASER_CONFIG_CHANNEL, 12) + @pytest.mark.parametrize("input_param, mock_response",[ (-10, (-14, -9)), (-8, (-12, -8)),