Skip to content

Commit 2983a23

Browse files
committed
[platform_api/chassis] Implement polling to get xcvr insert/remove event
1 parent 15479af commit 2983a23

File tree

1 file changed

+137
-3
lines changed
  • device/celestica/x86_64-cel_questone2bd-r0/sonic_platform

1 file changed

+137
-3
lines changed

device/celestica/x86_64-cel_questone2bd-r0/sonic_platform/chassis.py

+137-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
#############################################################################
1010

1111
try:
12-
import sys
13-
import re
12+
import json
1413
import os
14+
import re
15+
import sys
1516
import subprocess
16-
import json
17+
import time
1718
from sonic_platform_base.chassis_base import ChassisBase
1819
from helper import APIHelper
1920
except ImportError as e:
@@ -25,13 +26,24 @@
2526
NUM_THERMAL = 11
2627
NUM_SFP = 56
2728
NUM_COMPONENT = 7
29+
30+
SFP_PORT_START = 1
31+
SFP_PORT_END = 48
32+
QSFP_PORT_START = 49
33+
QSFP_PORT_END = 56
34+
2835
REBOOT_CAUSE_REG = "0xA106"
2936
TLV_EEPROM_I2C_BUS = 0
3037
TLV_EEPROM_I2C_ADDR = 56
3138

3239
BASE_CPLD_PLATFORM = "questone2bd.cpldb"
3340
BASE_GETREG_PATH = "/sys/devices/platform/{}/getreg".format(BASE_CPLD_PLATFORM)
3441

42+
SWITCH_BRD_PLATFORM = "questone2bd.switchboard"
43+
PORT_INFO_PATH = "/sys/devices/platform/{}/SFF".format(SWITCH_BRD_PLATFORM)
44+
PATH_INT_SYSFS = "{0}/{port_name}/{type_prefix}_isr_flags"
45+
PATH_INTMASK_SYSFS = "{0}/{port_name}/{type_prefix}_isr_mask"
46+
PATH_PRS_SYSFS = "{0}/{port_name}/{prs_file_name}"
3547

3648
class Chassis(ChassisBase):
3749
"""Platform-specific Chassis class"""
@@ -40,12 +52,14 @@ def __init__(self):
4052
ChassisBase.__init__(self)
4153
self._api_helper = APIHelper()
4254
self.sfp_module_initialized = False
55+
self.POLL_INTERVAL = 1
4356

4457
if not self._api_helper.is_host():
4558
self.__initialize_fan()
4659
self.__initialize_psu()
4760
self.__initialize_eeprom()
4861
self.__initialize_thermals()
62+
self.__initialize_interrupts()
4963
else:
5064
self.__initialize_components()
5165

@@ -85,6 +99,46 @@ def __initialize_components(self):
8599
component = Component(index)
86100
self._component_list.append(component)
87101

102+
def __initialize_interrupts(self):
103+
# Initial Interrupt MASK for QSFP, SFP
104+
sfp_info_obj = {}
105+
106+
present_en = 0x10
107+
Rxlos_IntL_en = 0x01
108+
event_mask = present_en
109+
110+
for index in range(NUM_SFP):
111+
port_num = index + 1
112+
if port_num in range(SFP_PORT_START, SFP_PORT_END+1):
113+
port_name = "SFP{}".format(str(port_num - SFP_PORT_START + 1))
114+
port_type = "sfp"
115+
sysfs_prs_file = "{}_modabs".format(port_type)
116+
elif port_num in range(QSFP_PORT_START, QSFP_PORT_END+1):
117+
port_name = "QSFP{}".format(str(port_num - QSFP_PORT_START + 1))
118+
port_type = "qsfp"
119+
sysfs_prs_file = "{}_modprs".format(port_type)
120+
121+
sfp_info_obj[index] = {}
122+
sfp_info_obj[index]['intmask_sysfs'] = PATH_INTMASK_SYSFS.format(
123+
PORT_INFO_PATH,
124+
port_name = port_name,
125+
type_prefix = port_type)
126+
127+
sfp_info_obj[index]['int_sysfs'] = PATH_INT_SYSFS.format(
128+
PORT_INFO_PATH,
129+
port_name = port_name,
130+
type_prefix = port_type)
131+
132+
sfp_info_obj[index]['prs_sysfs'] = PATH_PRS_SYSFS.format(
133+
PORT_INFO_PATH,
134+
port_name = port_name,
135+
prs_file_name = sysfs_prs_file)
136+
137+
self._api_helper.write_file(
138+
sfp_info_obj[index]["intmask_sysfs"], hex(event_mask))
139+
140+
self.sfp_info_obj = sfp_info_obj
141+
88142
def get_base_mac(self):
89143
"""
90144
Retrieves the base MAC address for the chassis
@@ -260,3 +314,83 @@ def get_status(self):
260314
A boolean value, True if device is operating properly, False if not
261315
"""
262316
return True
317+
318+
##############################################################
319+
###################### Event methods #########################
320+
##############################################################
321+
322+
def __is_port_device_present(self, port_idx):
323+
prs_path = self.sfp_info_obj[port_idx]["prs_sysfs"]
324+
is_present = 1 - int(self._api_helper.read_txt_file(prs_path))
325+
return is_present
326+
327+
def __update_port_event_object(self, interrup_devices):
328+
port_dict = {}
329+
event_obj = {'sfp':port_dict}
330+
for port_idx in interrup_devices:
331+
device_id = str(port_idx + 1)
332+
port_dict[device_id] = str(self.__is_port_device_present(port_idx))
333+
334+
if len(port_dict):
335+
event_obj['sfp'] = port_dict
336+
337+
return event_obj
338+
339+
def __check_all_port_interrupt_event(self):
340+
interrupt_devices = {}
341+
for i in range(NUM_SFP):
342+
int_sysfs = self.sfp_info_obj[i]["int_sysfs"]
343+
interrupt_flags = self._api_helper.read_txt_file(int_sysfs)
344+
if interrupt_flags != '0x00':
345+
interrupt_devices[i] = 1
346+
return interrupt_devices
347+
348+
def get_change_event(self, timeout=0):
349+
"""
350+
Returns a nested dictionary containing all devices which have
351+
experienced a change at chassis level
352+
Args:
353+
timeout: Timeout in milliseconds (optional). If timeout == 0,
354+
this method will block until a change is detected.
355+
Returns:
356+
(bool, dict):
357+
- True if call successful, False if not;
358+
- A nested dictionary where key is a device type,
359+
value is a dictionary with key:value pairs in the
360+
format of {'device_id':'device_event'},
361+
where device_id is the device ID for this device and
362+
device_event,
363+
status='1' represents device inserted,
364+
status='0' represents device removed.
365+
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
366+
indicates that fan 0 has been removed, fan 2
367+
has been inserted and sfp 11 has been removed.
368+
"""
369+
if timeout == 0:
370+
timer = self.POLL_INTERVAL
371+
while True:
372+
interrupt_devices = self.__check_all_port_interrupt_event()
373+
if len(interrupt_devices):
374+
break
375+
else:
376+
time.sleep(timer)
377+
events_dict = self.__update_port_event_object(interrupt_devices)
378+
return (True, events_dict)
379+
else:
380+
timeout = timeout / float(1000)
381+
timer = min(timeout, self.POLL_INTERVAL)
382+
383+
while True:
384+
start_time = time.time()
385+
interrupt_devices = self.__check_all_port_interrupt_event()
386+
if len(interrupt_devices):
387+
break
388+
389+
if timeout <= 0:
390+
break
391+
else:
392+
time.sleep(timer)
393+
elasped_time = time.time() - start_time
394+
timeout = round(timeout - elasped_time, 3)
395+
events_dict = self.__update_port_event_object(interrupt_devices)
396+
return (True, events_dict)

0 commit comments

Comments
 (0)