1616 import time
1717 import os
1818 import logging
19- import select
2019 from sonic_sfp .sfputilbase import SfpUtilBase
2120except 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
0 commit comments