Skip to content

Commit 94919de

Browse files
authored
[sfp-refactoring] Initial support for CMIS application initialization (#219)
1 parent 10ae99a commit 94919de

File tree

6 files changed

+601
-7
lines changed

6 files changed

+601
-7
lines changed

sonic_platform_base/sonic_xcvr/api/public/cmis.py

+201-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from ..xcvr_api import XcvrApi
1010

1111
import logging
12+
from ...codes.public.cmis import CmisCodes
13+
from ...codes.public.sff8024 import Sff8024
1214
from ...fields import consts
1315
from ..xcvr_api import XcvrApi
1416
from .cmisCDB import CmisCdbApi
@@ -50,6 +52,12 @@ def get_module_type(self):
5052
'''
5153
return self.xcvr_eeprom.read(consts.ID_FIELD)
5254

55+
def get_module_type_abbreviation(self):
56+
'''
57+
This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6
58+
'''
59+
return self.xcvr_eeprom.read(consts.ID_ABBRV_FIELD)
60+
5361
def get_connector_type(self):
5462
'''
5563
This function returns module connector. Table 4-3 in SFF-8024 Rev4.6
@@ -134,10 +142,10 @@ def get_transceiver_info(self):
134142
"nominal_bit_rate": 0, # Not supported
135143
"specification_compliance": admin_info[consts.MEDIA_TYPE_FIELD],
136144
"vendor_date": admin_info[consts.VENDOR_DATE_FIELD],
137-
"vendor_oui": admin_info[consts.VENDOR_OUI_FIELD],
138-
# TODO
139-
"application_advertisement": "N/A",
145+
"vendor_oui": admin_info[consts.VENDOR_OUI_FIELD]
140146
}
147+
appl_advt = self.get_application_advertisement()
148+
xcvr_info['application_advertisement'] = str(appl_advt) if len(appl_advt) > 0 else 'N/A'
141149
xcvr_info['host_electrical_interface'] = self.get_host_electrical_interface()
142150
xcvr_info['media_interface_code'] = self.get_module_media_interface()
143151
xcvr_info['host_lane_count'] = self.get_host_lane_count()
@@ -876,6 +884,24 @@ def reset_module(self, reset = False):
876884
else:
877885
return True
878886

887+
def reset(self):
888+
"""
889+
Reset SFP and return all user module settings to their default state.
890+
891+
Returns:
892+
A boolean, True if successful, False if not
893+
"""
894+
if self.reset_module(True):
895+
# minimum waiting time for the TWI to be functional again
896+
time.sleep(2)
897+
# buffer time
898+
for retries in range(5):
899+
state = self.get_module_state()
900+
if state in ['ModuleReady', 'ModuleLowPwr']:
901+
return True
902+
time.sleep(1)
903+
return False
904+
879905
def get_lpmode(self):
880906
'''
881907
Retrieves Low power module status
@@ -1745,4 +1771,176 @@ def get_transceiver_loopback(self):
17451771
for lane in range(1, self.NUM_CHANNELS+1):
17461772
trans_loopback['host_input_loopback_lane%d' % lane] = 'N/A'
17471773
return trans_loopback
1774+
1775+
def set_datapath_init(self, channel):
1776+
"""
1777+
Put the CMIS datapath into the initialized state
1778+
1779+
Args:
1780+
channel:
1781+
Integer, a bitmask of the lanes on the host side
1782+
e.g. 0x5 for lane 0 and lane 2.
1783+
1784+
Returns:
1785+
Boolean, true if success otherwise false
1786+
"""
1787+
cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION)
1788+
data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD)
1789+
for lane in range(self.NUM_CHANNELS):
1790+
if ((1 << lane) & channel) == 0:
1791+
continue
1792+
if cmis_major >= 4: # CMIS v4 onwards
1793+
data &= ~(1 << lane)
1794+
else: # CMIS v3
1795+
data |= (1 << lane)
1796+
self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data)
1797+
1798+
def set_datapath_deinit(self, channel):
1799+
"""
1800+
Put the CMIS datapath into the de-initialized state
1801+
1802+
Args:
1803+
channel:
1804+
Integer, a bitmask of the lanes on the host side
1805+
e.g. 0x5 for lane 0 and lane 2.
1806+
1807+
Returns:
1808+
Boolean, true if success otherwise false
1809+
"""
1810+
cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION)
1811+
data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD)
1812+
for lane in range(self.NUM_CHANNELS):
1813+
if ((1 << lane) & channel) == 0:
1814+
continue
1815+
if cmis_major >= 4: # CMIS v4 onwards
1816+
data |= (1 << lane)
1817+
else: # CMIS v3
1818+
data &= ~(1 << lane)
1819+
self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data)
1820+
1821+
def get_application_advertisement(self):
1822+
"""
1823+
Get the application advertisement of the CMIS transceiver
1824+
1825+
Returns:
1826+
Dictionary, the application advertisement
1827+
"""
1828+
map = {
1829+
Sff8024.MODULE_MEDIA_TYPE[1]: consts.MODULE_MEDIA_INTERFACE_850NM,
1830+
Sff8024.MODULE_MEDIA_TYPE[2]: consts.MODULE_MEDIA_INTERFACE_SM,
1831+
Sff8024.MODULE_MEDIA_TYPE[3]: consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER,
1832+
Sff8024.MODULE_MEDIA_TYPE[4]: consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE,
1833+
Sff8024.MODULE_MEDIA_TYPE[5]: consts.MODULE_MEDIA_INTERFACE_BASE_T
1834+
}
1835+
1836+
ret = {}
1837+
dic = self.xcvr_eeprom.read(consts.APPLS_ADVT_FIELD)
1838+
for app in range(1, 16):
1839+
buf = {}
1840+
1841+
key = "{}_{}".format(consts.HOST_ELECTRICAL_INTERFACE, app)
1842+
val = dic.get(key)
1843+
if val in [None, 'Unknown', 'Undefined']:
1844+
break
1845+
buf['host_electrical_interface_id'] = val
1846+
1847+
prefix = map.get(self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD))
1848+
if prefix is None:
1849+
break
1850+
key = "{}_{}".format(prefix, app)
1851+
val = dic.get(key)
1852+
if val in [None, 'Unknown', 'Undefined']:
1853+
break
1854+
buf['module_media_interface_id'] = val
1855+
1856+
key = "{}_{}".format(consts.MEDIA_LANE_COUNT, app)
1857+
val = dic.get(key)
1858+
if val is None:
1859+
break
1860+
buf['media_lane_count'] = val
1861+
1862+
key = "{}_{}".format(consts.HOST_LANE_COUNT, app)
1863+
val = dic.get(key)
1864+
if val is None:
1865+
break
1866+
buf['host_lane_count'] = val
1867+
1868+
key = "{}_{}".format(consts.HOST_LANE_ASSIGNMENT_OPTION, app)
1869+
val = dic.get(key)
1870+
if val is None:
1871+
break
1872+
buf['host_lane_assignment_options'] = val
1873+
1874+
ret[app] = buf
1875+
return ret
1876+
1877+
def get_application(self, lane):
1878+
"""
1879+
Get the CMIS selected application code of a host lane
1880+
1881+
Args:
1882+
lane:
1883+
Integer, the zero-based lane id on the host side
1884+
1885+
Returns:
1886+
Integer, the transceiver-specific application code
1887+
"""
1888+
appl = 0
1889+
if lane in range(self.NUM_CHANNELS) and not self.is_flat_memory():
1890+
name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
1891+
appl = self.xcvr_eeprom.read(name) >> 4
1892+
1893+
return (appl & 0xf)
1894+
1895+
def set_application(self, channel, appl_code):
1896+
"""
1897+
Update the selected application code to the specified lanes on the host side
1898+
1899+
Args:
1900+
channel:
1901+
Integer, a bitmask of the lanes on the host side
1902+
e.g. 0x5 for lane 0 and lane 2.
1903+
appl_code:
1904+
Integer, the desired application code
1905+
1906+
Returns:
1907+
Boolean, true if success otherwise false
1908+
"""
1909+
# Update the application selection
1910+
lane_first = -1
1911+
for lane in range(self.NUM_CHANNELS):
1912+
if ((1 << lane) & channel) == 0:
1913+
continue
1914+
if lane_first < 0:
1915+
lane_first = lane
1916+
addr = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
1917+
data = (appl_code << 4) | (lane_first << 1)
1918+
self.xcvr_eeprom.write(addr, data)
1919+
1920+
# Apply DataPathInit
1921+
return self.xcvr_eeprom.write("%s_%d" % (consts.STAGED_CTRL_APPLY_DPINIT_FIELD, 0), channel)
1922+
1923+
def get_error_description(self):
1924+
dp_state = self.get_datapath_state()
1925+
conf_state = self.get_config_datapath_hostlane_status()
1926+
for lane in range(self.NUM_CHANNELS):
1927+
name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1)
1928+
appl = self.xcvr_eeprom.read(name)
1929+
if (appl is None) or ((appl >> 4) == 0):
1930+
continue
1931+
1932+
name = "DP{}State".format(lane + 1)
1933+
if dp_state[name] != CmisCodes.DATAPATH_STATE[4]:
1934+
return dp_state[name]
1935+
1936+
name = "ConfigStatusLane{}".format(lane + 1)
1937+
if conf_state[name] != CmisCodes.CONFIG_STATUS[1]:
1938+
return conf_state[name]
1939+
1940+
state = self.get_module_state()
1941+
if state != CmisCodes.MODULE_STATE[3]:
1942+
return state
1943+
1944+
return None
1945+
17481946
# TODO: other XcvrApi methods

sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, xcvr_eeprom):
2626
super(CmisCdbApi, self).__init__(xcvr_eeprom)
2727
self.cdb_instance_supported = self.xcvr_eeprom.read(consts.CDB_SUPPORT)
2828
self.failed_status_dict = self.xcvr_eeprom.mem_map.codes.CDB_FAIL_STATUS
29-
assert self.cdb_instance_supported != 0
29+
#assert self.cdb_instance_supported != 0
3030

3131
def cdb1_chkflags(self):
3232
'''

sonic_platform_base/sonic_xcvr/fields/consts.py

+7
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@
270270
TRANS_CONFIG_FIELD = "TransceiverConfig"
271271
MODULE_LEVEL_CONTROL = "ModuleControl"
272272

273+
APPLS_ADVT_FIELD = "Applications Advertisement"
273274
CTRLS_ADVT_FIELD = "Supported Controls Advertisement"
274275
FLAGS_ADVT_FIELD = "Supported Flags Advertisement"
275276
PAGE_SUPPORT_ADVT_FIELD = "Supported Pages Advertisement"
@@ -278,13 +279,19 @@
278279
LANE_MON_ADVT_FIELD = "Supported Lane Monitor Advertisement"
279280
LANE_DATAPATH_CTRL_FIELD = "Lane Control and Data Path Control"
280281
LANE_DATAPATH_STATUS_FIELD = "Lane Status and Data Path Status"
282+
DATAPATH_DEINIT_FIELD = "Data Path Deinit"
281283
LEN_MULT_FIELD = "LengthMultiplier"
282284
MAX_POWER_FIELD = "MaxPower"
283285
MGMT_CHAR_FIELD = "Management Characteristics"
284286
MGMT_CHAR_MISC_FIELD = "Management Characteristics (Misc)"
285287

286288
MODULE_CHAR_ADVT_FIELD = "Module Characteristics Advertising"
287289

290+
STAGED_CTRL_FIELD = "Staged Control Set"
291+
STAGED_CTRL_APPLY_DPINIT_FIELD = "Staged Control Set Apply DataPathInit"
292+
STAGED_CTRL_APPLY_IMMEDIATE_FIELD = "Staged Control Set Apply Immediate"
293+
STAGED_CTRL_APSEL_FIELD = "Staged Control Set ApSel"
294+
288295
# C-CMIS
289296

290297
# Module configuration support fields

0 commit comments

Comments
 (0)