Skip to content

Commit

Permalink
[device/celestica]: Add xcvrd event support for Seastone-DX010 (#5896)
Browse files Browse the repository at this point in the history
- Add sysfs interrupt to notify userspace app of external interrupt
- Implement get_change_event() in chassis api.
  • Loading branch information
Wirut Getbamrung authored Dec 14, 2020
1 parent 9580b04 commit 4257c79
Show file tree
Hide file tree
Showing 7 changed files with 1,419 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
try:
import sys
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
from sonic_py_common import device_info
from .event import SfpEvent
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
Expand Down Expand Up @@ -45,9 +48,14 @@ def __init__(self):
self.__initialize_components()

def __initialize_sfp(self):
sfputil_helper = SfpUtilHelper()
port_config_file_path = device_info.get_path_to_port_config_file()
sfputil_helper.read_porttab_mappings(port_config_file_path, 0)

from sonic_platform.sfp import Sfp
for index in range(0, NUM_SFP):
sfp = Sfp(index)
name_idx = 0 if index+1 == NUM_SFP else index+1
sfp = Sfp(index, sfputil_helper.logical[name_idx])
self._sfp_list.append(sfp)
self.sfp_module_initialized = True

Expand Down Expand Up @@ -141,6 +149,38 @@ def get_reboot_cause(self):

return prev_reboot_cause


def get_change_event(self, timeout=0):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the format of
{'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
# SFP event
if not self.sfp_module_initialized:
self.__initialize_sfp()

sfp_event = SfpEvent(self._sfp_list).get_sfp_event(timeout)
if sfp_event:
return True, {'sfp': sfp_event}

return False, {'sfp': {}}

##############################################################
######################## SFP methods #########################
##############################################################
Expand Down
52 changes: 52 additions & 0 deletions device/celestica/x86_64-cel_seastone-r0/sonic_platform/event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
try:
import select
from .helper import APIHelper
from sonic_py_common.logger import Logger
except ImportError as e:
raise ImportError(repr(e) + " - required module not found")


class SfpEvent:
''' Listen to insert/remove sfp events '''

QSFP_MODPRS_IRQ = '/sys/devices/platform/dx010_cpld/qsfp_modprs_irq'
GPIO_SUS6 = "/sys/devices/platform/slx-ich.0/sci_int_gpio_sus6"

def __init__(self, sfp_list):
self._api_helper = APIHelper()
self._sfp_list = sfp_list
self._logger = Logger()

def get_sfp_event(self, timeout):
epoll = select.epoll()
port_dict = {}
timeout_sec = timeout/1000

try:
# We get notified when there is an SCI interrupt from GPIO SUS6
fd = open(self.GPIO_SUS6, "r")
fd.read()

epoll.register(fd.fileno(), select.EPOLLIN & select.EPOLLET)
events = epoll.poll(timeout=timeout_sec if timeout != 0 else -1)
if events:
# Read the QSFP ABS interrupt & status registers
port_changes = self._api_helper.read_one_line_file(
self.QSFP_MODPRS_IRQ)
changes = int(port_changes, 16)
for sfp in self._sfp_list:
change = (changes >> sfp.port_num-1) & 1
if change == 1:
port_dict[str(sfp.port_num)] = str(
int(sfp.get_presence()))

return port_dict
except Exception as e:
self._logger.log_error("Failed to detect SfpEvent - " + repr(e))
return False

finally:
fd.close()
epoll.close()

return False
20 changes: 3 additions & 17 deletions device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
Expand Down Expand Up @@ -166,19 +165,16 @@ class Sfp(SfpBase):
RESET_PATH = "/sys/devices/platform/dx010_cpld/qsfp_reset"
LP_PATH = "/sys/devices/platform/dx010_cpld/qsfp_lpmode"
PRS_PATH = "/sys/devices/platform/dx010_cpld/qsfp_modprs"
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"

def __init__(self, sfp_index):
def __init__(self, sfp_index, sfp_name):
SfpBase.__init__(self)
# Init index
self.index = sfp_index
self.port_num = self.index + 1
self.dom_supported = False
self.sfp_type, self.port_name = self.__get_sfp_info()
self._api_helper = APIHelper()
self.platform = self._api_helper.platform
self.hwsku = self._api_helper.hwsku
self.name = sfp_name

# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
Expand Down Expand Up @@ -233,12 +229,6 @@ def __convert_string_to_num(self, value_str):
else:
return 'N/A'

def __get_path_to_port_config_file(self):
platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.platform])
hwsku_path = "/".join([platform_path, self.hwsku]
) if self._api_helper.is_host() else self.PMON_HWSKU_PATH
return "/".join([hwsku_path, "port_config.ini"])

def __read_eeprom_specific_bytes(self, offset, num_bytes):
sysfsfile_eeprom = None
eeprom_raw = []
Expand Down Expand Up @@ -1317,11 +1307,7 @@ def get_name(self):
Returns:
string: The name of the device
"""
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
name = sfputil_helper.logical[self.index] or "Unknown"
return name
return self.name

def get_presence(self):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ start)
modprobe dx010_wdt
modprobe leds-dx010
modprobe lm75
modprobe slx_gpio_ich

found=0
for devnum in 0 1; do
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
obj-m := dx010_cpld.o mc24lc64t.o emc2305.o dx010_wdt.o leds-dx010.o
obj-m := dx010_cpld.o mc24lc64t.o emc2305.o dx010_wdt.o leds-dx010.o slx_gpio_ich.o
Loading

0 comments on commit 4257c79

Please sign in to comment.