14
14
from ctypes import create_string_buffer
15
15
16
16
try :
17
+ from sonic_py_common .logger import Logger
17
18
from sonic_platform_base .sonic_xcvr .sfp_optoe_base import SfpOptoeBase
18
19
from sonic_platform_base .sonic_sfp .sfputilhelper import SfpUtilHelper
19
20
from sonic_platform_base .sonic_sfp .sff8436 import sff8436Dom
31
32
QSFP_CONTROL_OFFSET = 86
32
33
QSFP_POWEROVERRIDE_OFFSET = 93
33
34
34
- SFP_TYPE_CODE_LIST = [
35
- 0x03 , # SFP/SFP+/SFP28
36
- 0x0b # DWDM-SFP/SFP+
37
- ]
38
- QSFP_TYPE_CODE_LIST = [
39
- 0x0c , # QSFP
40
- 0x0d , # QSFP+ or later
41
- 0x11 , # QSFP28 or later
42
- 0xE1 # QSFP28 EDFA
43
- ]
44
- QSFP_DD_TYPE_CODE_LIST = [
45
- 0x18 # QSFP-DD Double Density 8X Pluggable Transceiver
46
- ]
47
-
48
- SFP_TYPE = "SFP"
49
- QSFP_TYPE = "QSFP"
50
- OSFP_TYPE = "OSFP"
51
- QSFP_DD_TYPE = "QSFP_DD"
52
-
53
35
NULL_VAL = 'N/A'
54
36
55
37
62
44
PCIE_UDB_BIND_PATH = "/sys/bus/platform/drivers/pcie_udb_fpga_device/{0}"
63
45
PCIE_LDB_BIND_PATH = "/sys/bus/platform/drivers/pcie_ldb_fpga_device/{0}"
64
46
47
+ logger = Logger ()
65
48
class Sfp (SfpOptoeBase ):
66
49
"""Platform-specific Sfp class"""
67
50
HOST_CHK_CMD = "which systemctl > /dev/null 2>&1"
@@ -72,6 +55,32 @@ class Sfp(SfpOptoeBase):
72
55
QSFP_PORT_START = 1
73
56
QSFP_PORT_END = 64
74
57
58
+ SFP_TYPE_CODE_LIST = [
59
+ 0x03 , # SFP/SFP+/SFP28
60
+ 0x0b # DWDM-SFP/SFP+
61
+ ]
62
+ QSFP_TYPE_CODE_LIST = [
63
+ 0x0c , # QSFP
64
+ 0x0d , # QSFP+ or later
65
+ 0x11 , # QSFP28 or later
66
+ 0xe1 # QSFP28 EDFA
67
+ ]
68
+ QSFP_DD_TYPE_CODE_LIST = [
69
+ 0x18 # QSFP-DD Double Density 8X Pluggable Transceiver
70
+ ]
71
+ OSFP_TYPE_CODE_LIST = [
72
+ 0x19 # OSFP
73
+ ]
74
+
75
+ SFP_TYPE = "SFP"
76
+ QSFP_TYPE = "QSFP"
77
+ OSFP_TYPE = "OSFP"
78
+ QSFP_DD_TYPE = "QSFP_DD"
79
+
80
+ UPDATE_DONE = "Done"
81
+ EEPROM_DATA_NOT_READY = "eeprom not ready"
82
+ UNKNOWN_SFP_TYPE_ID = "unknow sfp ID"
83
+
75
84
# Path to sysfs
76
85
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
77
86
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
@@ -91,13 +100,15 @@ def __init__(self, sfp_index=0, sfp_name=None):
91
100
self ._api_helper = APIHelper ()
92
101
self ._name = sfp_name
93
102
94
- self ._refresh_optoe_dev_class ()
103
+ self .sfp_type = self .QSFP_TYPE
104
+ self .update_sfp_type ()
105
+ self .refresh_optoe_dev_class ()
95
106
96
107
def __write_txt_file (self , file_path , value ):
97
108
try :
98
109
reg_file = open (file_path , "w" )
99
110
except IOError as e :
100
- print ("Error: unable to open file: %s" % str (e ))
111
+ logger . log_error ("Error: unable to open file: %s" % str (e ))
101
112
return False
102
113
103
114
reg_file .write (str (value ))
@@ -165,25 +176,19 @@ def read_eeprom(self, offset, num_bytes):
165
176
except (OSError , IOError ):
166
177
return None
167
178
168
- def _detect_sfp_type (self ):
169
- sfp_type = QSFP_TYPE
170
- eeprom_raw = []
171
- eeprom_raw = self .read_eeprom (XCVR_TYPE_OFFSET , XCVR_TYPE_WIDTH )
172
- if eeprom_raw :
173
- if eeprom_raw [0 ] in SFP_TYPE_CODE_LIST :
174
- self .sfp_type = SFP_TYPE
175
- elif eeprom_raw [0 ] in QSFP_TYPE_CODE_LIST :
176
- self .sfp_type = QSFP_TYPE
177
- elif eeprom_raw [0 ] in QSFP_DD_TYPE_CODE_LIST :
178
- self .sfp_type = QSFP_DD_TYPE
179
- else :
180
- self .sfp_type = sfp_type
181
- else :
182
- self .sfp_type = sfp_type
183
179
184
- def _refresh_optoe_dev_class (self ):
185
- self ._detect_sfp_type ()
180
+ def write_eeprom (self , offset , num_bytes , write_buffer ):
181
+ try :
182
+ with open (self .get_eeprom_path (), mode = 'r+b' , buffering = 0 ) as f :
183
+ for i in range (num_bytes ):
184
+ f .seek (offset + i )
185
+ f .write (write_buffer [i :i + 1 ])
186
+ except (OSError , IOError ):
187
+ return False
188
+ return True
186
189
190
+
191
+ def refresh_optoe_dev_class (self ):
187
192
if self .index < 32 :
188
193
port = "pcie_udb_fpga_device.{}" .format (self .index )
189
194
port_dev_unbind = PCIE_UDB_BIND_PATH .format ("unbind" )
@@ -193,17 +198,8 @@ def _refresh_optoe_dev_class(self):
193
198
port_dev_unbind = PCIE_LDB_BIND_PATH .format ("unbind" )
194
199
port_dev_bind = PCIE_LDB_BIND_PATH .format ("bind" )
195
200
196
- if self .sfp_type == QSFP_TYPE :
197
- self ._api_helper .write_txt_file (port_dev_unbind , port )
198
- self ._api_helper .write_txt_file (port_dev_bind , port )
199
- elif self .sfp_type == SFP_TYPE :
200
- self ._api_helper .write_txt_file (port_dev_unbind , port )
201
- self ._api_helper .write_txt_file (port_dev_bind , port )
202
- elif self .sfp_type == QSFP_DD_TYPE :
203
- self ._api_helper .write_txt_file (port_dev_unbind , port )
204
- self ._api_helper .write_txt_file (port_dev_bind , port )
205
- else :
206
- return False
201
+ self ._api_helper .write_txt_file (port_dev_unbind , port )
202
+ self ._api_helper .write_txt_file (port_dev_bind , port )
207
203
208
204
def get_reset_status (self ):
209
205
"""
@@ -247,13 +243,17 @@ def get_lpmode(self):
247
243
# SFP doesn't support this feature
248
244
return False
249
245
250
- lpmode_path = "{}{}{}" .format (FPGA_PCIE_PATH , '/module_lp_mode_' , self .port_num )
251
-
252
- val = self ._api_helper .read_txt_file (lpmode_path )
253
- if val is not None :
254
- return int (val , 10 )== 1
246
+ if self .sfp_type == self .QSFP_DD_TYPE :
247
+ api = self .get_xcvr_api ()
248
+ return api .get_lpmode ()
255
249
else :
256
- return False
250
+ lpmode_path = "{}{}{}" .format (FPGA_PCIE_PATH , '/module_lp_mode_' , self .port_num )
251
+
252
+ val = self ._api_helper .read_txt_file (lpmode_path )
253
+ if val is not None :
254
+ return int (val , 10 )== 1
255
+ else :
256
+ return False
257
257
258
258
def reset (self ):
259
259
"""
@@ -289,7 +289,7 @@ def tx_disable(self, tx_disable):
289
289
Returns:
290
290
A boolean, True if tx_disable is set successfully, False if not
291
291
"""
292
- if self .sfp_type == QSFP_TYPE :
292
+ if self .sfp_type == self . QSFP_TYPE :
293
293
sysfsfile_eeprom = None
294
294
try :
295
295
tx_disable_value = 0xf if tx_disable else 0x0
@@ -321,14 +321,19 @@ def set_lpmode(self, lpmode):
321
321
if not self .get_presence ():
322
322
return False
323
323
324
- lpmode_path = "{}{}{}" .format (FPGA_PCIE_PATH , 'module_lp_mode_' , self .port_num )
324
+ if self .sfp_type == self .QSFP_DD_TYPE :
325
+ api = self .get_xcvr_api ()
326
+ api .set_lpmode (lpmode )
327
+ return True
328
+ else :
329
+ lpmode_path = "{}{}{}" .format (FPGA_PCIE_PATH , 'module_lp_mode_' , self .port_num )
325
330
326
- if lpmode is True :
327
- ret = self .__write_txt_file (lpmode_path , 1 ) #enable lpmode
328
- else :
329
- ret = self .__write_txt_file (lpmode_path , 0 ) #disable lpmode
331
+ if lpmode is True :
332
+ ret = self .__write_txt_file (lpmode_path , 1 ) #enable lpmode
333
+ else :
334
+ ret = self .__write_txt_file (lpmode_path , 0 ) #disable lpmode
330
335
331
- return ret
336
+ return ret
332
337
333
338
def _convert_raw_to_byte (self , raw , num_bytes ):
334
339
"""
@@ -414,7 +419,7 @@ def set_power_override(self, power_override, power_set):
414
419
fd .close ()
415
420
416
421
except Exception as e :
417
- print ( ' Error: unable to open file: ' , str (e ))
422
+ logger . log_error ( " Error: unable to open file: %s" % str (e ))
418
423
return False
419
424
420
425
return True
@@ -471,3 +476,28 @@ def is_replaceable(self):
471
476
A boolean value, True if replaceable
472
477
"""
473
478
return True
479
+
480
+ def update_sfp_type (self ):
481
+ """
482
+ Updates the sfp type
483
+
484
+ """
485
+ ret = self .UPDATE_DONE
486
+ eeprom_raw = []
487
+ eeprom_raw = self .read_eeprom (0 , 1 )
488
+ if eeprom_raw and hasattr (self ,'sfp_type' ):
489
+ if eeprom_raw [0 ] in self .SFP_TYPE_CODE_LIST :
490
+ self .sfp_type = self .SFP_TYPE
491
+ elif eeprom_raw [0 ] in self .QSFP_TYPE_CODE_LIST :
492
+ self .sfp_type = self .QSFP_TYPE
493
+ elif eeprom_raw [0 ] in self .QSFP_DD_TYPE_CODE_LIST :
494
+ self .sfp_type = self .QSFP_DD_TYPE
495
+ elif eeprom_raw [0 ] in self .OSFP_TYPE_CODE_LIST :
496
+ self .sfp_type = self .OSFP_TYPE
497
+ else :
498
+ ret = self .UNKNOWN_SFP_TYPE_ID
499
+ else :
500
+ ret = self .EEPROM_DATA_NOT_READY
501
+
502
+ return ret
503
+
0 commit comments