Skip to content

Commit 7a65e22

Browse files
aravindmani-1Carl Keene
authored andcommitted
Dell S6100: Modify transceiver change event from interrupt to poll mode (sonic-net#7309)
#### Why I did it - xcvrd crash was seen in latest 201811 images. - For Dell S6100,API 2.0 uses poll mode while 1.0 was still using interrupt mode. #### How I did it - Modified get_transceiver_change_event in 1.0 to poll mode.
1 parent a878a79 commit 7a65e22

2 files changed

Lines changed: 78 additions & 135 deletions

File tree

device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py

Lines changed: 78 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import time
1717
import os
1818
import logging
19-
import select
2019
from sonic_sfp.sfputilbase import SfpUtilBase
2120
except ImportError as e:
2221
raise ImportError("%s - required module not found" % str(e))
@@ -28,7 +27,7 @@ class SfpUtil(SfpUtilBase):
2827
PORT_START = 0
2928
PORT_END = 63
3029
PORTS_IN_BLOCK = 64
31-
30+
POLL_INTERVAL = 1
3231
_port_to_eeprom_mapping = {}
3332
_port_to_i2c_mapping = {
3433
0: [6, 18, 34, 50, 66],
@@ -110,7 +109,6 @@ class SfpUtil(SfpUtilBase):
110109
IOM_4_PORT_END = 63
111110

112111
BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
113-
OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6"
114112

115113
oir_fd = -1
116114
epoll = -1
@@ -235,8 +233,8 @@ def __init__(self):
235233
elif (not assigned):
236234
self.port_to_eeprom_mapping[port_num] =\
237235
"No IOM"
238-
239236
SfpUtilBase.__init__(self)
237+
self._transceiver_presence = self._get_transceiver_presence()
240238

241239
def __del__(self):
242240
if self.oir_fd != -1:
@@ -482,7 +480,7 @@ def reset(self, port_num):
482480
def get_register(self, reg_file):
483481
retval = 'ERR'
484482

485-
if (not os.path.isfile(reg_file)):
483+
if not os.path.isfile(reg_file):
486484
print(reg_file + ' not found !')
487485
return retval
488486

@@ -496,141 +494,88 @@ def get_register(self, reg_file):
496494
retval = retval.lstrip(" ")
497495
return retval
498496

499-
def check_interrupts(self, port_dict):
500-
retval = 0
501-
is_port_dict_updated = False
502-
503-
# Read the QSFP ABS interrupt & status registers
504-
cpld2_abs_int = self.get_register(
505-
"/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int")
506-
cpld2_abs_sta = self.get_register(
507-
"/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta")
508-
cpld3_abs_int = self.get_register(
509-
"/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int")
510-
cpld3_abs_sta = self.get_register(
511-
"/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta")
512-
cpld4_abs_int = self.get_register(
513-
"/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int")
514-
cpld4_abs_sta = self.get_register(
515-
"/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta")
516-
cpld5_abs_int = self.get_register(
517-
"/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_int")
518-
cpld5_abs_sta = self.get_register(
519-
"/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_sta")
520-
521-
if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or
522-
cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or
523-
cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR' or
524-
cpld5_abs_int == 'ERR' or cpld5_abs_sta == 'ERR'):
525-
return -1
526-
527-
# If IOM is not present, interrupt will return 'read error'
497+
def _get_transceiver_presence(self):
498+
499+
cpld2_modprs = self.get_register(
500+
"/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_modprs")
501+
cpld3_modprs = self.get_register(
502+
"/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_modprs")
503+
cpld4_modprs = self.get_register(
504+
"/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_modprs")
505+
cpld5_modprs = self.get_register(
506+
"/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_modprs")
507+
508+
# If IOM is not present, register read will fail.
528509
# Handle the scenario gracefully
529-
if (cpld2_abs_int == 'read error'):
530-
cpld2_abs_int = "0x0"
531-
cpld2_abs_sta = "0x0"
532-
if (cpld3_abs_int == 'read error'):
533-
cpld3_abs_int = "0x0"
534-
cpld3_abs_sta = "0x0"
535-
if (cpld4_abs_int == 'read error'):
536-
cpld4_abs_int = "0x0"
537-
cpld4_abs_sta = "0x0"
538-
if (cpld5_abs_int == 'read error'):
539-
cpld5_abs_int = "0x0"
540-
cpld5_abs_sta = "0x0"
541-
542-
cpld2_abs_int = int(cpld2_abs_int, 16)
543-
cpld2_abs_sta = int(cpld2_abs_sta, 16)
544-
cpld3_abs_int = int(cpld3_abs_int, 16)
545-
cpld3_abs_sta = int(cpld3_abs_sta, 16)
546-
cpld4_abs_int = int(cpld4_abs_int, 16)
547-
cpld4_abs_sta = int(cpld4_abs_sta, 16)
548-
cpld5_abs_int = int(cpld5_abs_int, 16)
549-
cpld5_abs_sta = int(cpld5_abs_sta, 16)
510+
if cpld2_modprs == 'read error' or cpld2_modprs == 'ERR':
511+
cpld2_modprs = '0x0'
512+
if cpld3_modprs == 'read error' or cpld3_modprs == 'ERR':
513+
cpld3_modprs = '0x0'
514+
if cpld4_modprs == 'read error' or cpld4_modprs == 'ERR':
515+
cpld4_modprs = '0x0'
516+
if cpld5_modprs == 'read error' or cpld5_modprs == 'ERR':
517+
cpld5_modprs = '0x0'
550518

551519
# Make it contiguous
552-
interrupt_reg = (cpld2_abs_int & 0xffff) | \
553-
((cpld4_abs_int & 0xffff) << 16) | \
554-
((cpld3_abs_int & 0xffff) << 32) | \
555-
((cpld5_abs_int & 0xffff) << 48)
556-
status_reg = (cpld2_abs_sta & 0xffff) | \
557-
((cpld4_abs_sta & 0xffff) << 16) | \
558-
((cpld3_abs_sta & 0xffff) << 32) | \
559-
((cpld5_abs_sta & 0xffff) << 48)
560-
561-
port = self.port_start
562-
while port <= self.port_end:
563-
if interrupt_reg & (1 << port):
564-
# update only if atleast one port has generated
565-
# interrupt
566-
is_port_dict_updated = True
567-
if status_reg & (1 << port):
568-
# status reg 1 => optics is removed
569-
port_dict[port] = '0'
570-
else:
571-
# status reg 0 => optics is inserted
572-
port_dict[port] = '1'
573-
port += 1
574-
return retval, is_port_dict_updated
520+
transceiver_presence = (int(cpld2_modprs, 16) & 0xffff) |\
521+
((int(cpld4_modprs, 16) & 0xffff) << 16) |\
522+
((int(cpld3_modprs, 16) & 0xffff) << 32) |\
523+
((int(cpld5_modprs, 16) & 0xffff) << 48)
524+
525+
return transceiver_presence
575526

576527
def get_transceiver_change_event(self, timeout=0):
528+
"""
529+
Returns a dictionary containing optics insertion/removal status.
530+
Args:
531+
timeout: Timeout in milliseconds (optional). If timeout == 0,
532+
this method will block until a change is detected.
533+
Returns:
534+
(bool, dict):
535+
- True if call successful, False if not;
536+
"""
577537
port_dict = {}
578-
try:
579-
# We get notified when there is an SCI interrupt from GPIO SUS6
580-
# Open the sysfs file and register the epoll object
581-
self.oir_fd = open(self.OIR_FD_PATH, "r")
582-
if self.oir_fd != -1:
583-
# Do a dummy read before epoll register
584-
self.oir_fd.read()
585-
self.epoll = select.epoll()
586-
self.epoll.register(self.oir_fd.fileno(),
587-
select.EPOLLIN & select.EPOLLET)
588-
else:
589-
print("get_transceiver_change_event : unable to create fd")
590-
return False, {}
538+
forever = False
591539

592-
# Check for missed interrupts by invoking self.check_interrupts
593-
# which will update the port_dict.
594-
while True:
595-
interrupt_count_start = self.get_register(self.OIR_FD_PATH)
596-
597-
retval, is_port_dict_updated = \
598-
self.check_interrupts(port_dict)
599-
if ((retval == 0) and (is_port_dict_updated is True)):
600-
return True, port_dict
601-
602-
interrupt_count_end = self.get_register(self.OIR_FD_PATH)
603-
604-
if (interrupt_count_start == 'ERR' or
605-
interrupt_count_end == 'ERR'):
606-
print("get_transceiver_change_event : \
607-
unable to retrive interrupt count")
608-
break
540+
if timeout == 0:
541+
forever = True
542+
elif timeout > 0:
543+
timeout = timeout / float(1000) # Convert to secs
544+
else:
545+
return False, port_dict # Incorrect timeout
609546

610-
# check_interrupts() itself may take upto 100s of msecs.
611-
# We detect a missed interrupt based on the count
612-
if interrupt_count_start == interrupt_count_end:
547+
while True:
548+
if forever:
549+
timer = self.POLL_INTERVAL
550+
else:
551+
timer = min(timeout, self.POLL_INTERVAL)
552+
start_time = time.time()
553+
554+
time.sleep(timer)
555+
cur_presence = self._get_transceiver_presence()
556+
557+
# Update dict only if a change has been detected
558+
if cur_presence != self._transceiver_presence:
559+
changed_ports = self._transceiver_presence ^ cur_presence
560+
for port in range(self.port_end):
561+
# Mask off the bit corresponding to particular port
562+
mask = 1 << port
563+
if changed_ports & mask:
564+
# qsfp_modprs 1 => optics is removed
565+
if cur_presence & mask:
566+
port_dict[port] = '0'
567+
# qsfp_modprs 0 => optics is inserted
568+
else:
569+
port_dict[port] = '1'
570+
571+
# Update current presence
572+
self._transceiver_presence = cur_presence
573+
break
574+
575+
if not forever:
576+
elapsed_time = time.time() - start_time
577+
timeout = round(timeout - elapsed_time, 3)
578+
if timeout <= 0:
613579
break
614580

615-
# Block until an xcvr is inserted or removed with timeout = -1
616-
events = self.epoll.poll(
617-
timeout=timeout if timeout != 0 else -1)
618-
if events:
619-
# check interrupts and return the port_dict
620-
retval, is_port_dict_updated = \
621-
self.check_interrupts(port_dict)
622-
if (retval != 0):
623-
return False, {}
624-
625-
return True, port_dict
626-
except:
627-
return False, {}
628-
finally:
629-
if self.oir_fd != -1:
630-
self.epoll.unregister(self.oir_fd.fileno())
631-
self.epoll.close()
632-
self.oir_fd.close()
633-
self.oir_fd = -1
634-
self.epoll = -1
635-
636-
return False, {}
581+
return True, port_dict

platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ if [[ "$1" == "init" ]]; then
2828
pericom="/sys/bus/pci/devices/0000:08:00.0"
2929
modprobe i2c-dev
3030
modprobe i2c-mux-pca954x force_deselect_on_exit=1
31-
modprobe dell_ich
3231
modprobe dell_s6100_iom_cpld
3332
modprobe dell_s6100_lpc
3433
modprobe nvram
@@ -60,7 +59,6 @@ elif [[ "$1" == "deinit" ]]; then
6059
modprobe -r dell_s6100_iom_cpld
6160
modprobe -r i2c-mux-pca954x
6261
modprobe -r i2c-dev
63-
modprobe -r dell_ich
6462
modprobe -r nvram
6563
remove_python_api_package
6664
else

0 commit comments

Comments
 (0)