@@ -1073,6 +1073,12 @@ def get_cmis_application_desired(self, api, channel, speed):
10731073
10741074 return (appl_code & 0xf )
10751075
1076+ def get_cmis_dp_init_duration_secs (self , api ):
1077+ return api .get_datapath_init_duration ()/ 1000
1078+
1079+ def get_cmis_dp_deinit_duration_secs (self , api ):
1080+ return api .get_datapath_deinit_duration ()/ 1000
1081+
10761082 def is_cmis_application_update_required (self , api , channel , speed ):
10771083 """
10781084 Check if the CMIS application update is required
@@ -1176,6 +1182,32 @@ def check_config_error(self, api, channel, states):
11761182
11771183 return done
11781184
1185+ def check_datapath_init_pending (self , api , channel ):
1186+ """
1187+ Check if the CMIS datapath init is pending
1188+
1189+ Args:
1190+ api:
1191+ XcvrApi object
1192+ channel:
1193+ Integer, a bitmask of the lanes on the host side
1194+ e.g. 0x5 for lane 0 and lane 2.
1195+
1196+ Returns:
1197+ Boolean, true if all lanes are pending datapath init, otherwise false
1198+ """
1199+ pending = True
1200+ dpinit_pending_dict = api .get_dpinit_pending ()
1201+ for lane in range (self .CMIS_NUM_CHANNELS ):
1202+ if ((1 << lane ) & channel ) == 0 :
1203+ continue
1204+ key = "DPInitPending{}" .format (lane + 1 )
1205+ if not dpinit_pending_dict [key ]:
1206+ pending = False
1207+ break
1208+
1209+ return pending
1210+
11791211 def check_datapath_state (self , api , channel , states ):
11801212 """
11811213 Check if the CMIS datapath states are in the specified state
@@ -1458,7 +1490,9 @@ def task_worker(self):
14581490 # TODO: Make sure this doesn't impact other datapaths
14591491 api .set_lpmode (False )
14601492 self .port_dict [lport ]['cmis_state' ] = self .CMIS_STATE_AP_CONF
1461- self .port_dict [lport ]['cmis_expired' ] = now + datetime .timedelta (seconds = self .CMIS_DEF_EXPIRED )
1493+ dpDeinitDuration = self .get_cmis_dp_deinit_duration_secs (api )
1494+ self .log_notice ("{} DpDeinit duration {} secs" .format (lport , dpDeinitDuration ))
1495+ self .port_dict [lport ]['cmis_expired' ] = now + datetime .timedelta (seconds = dpDeinitDuration )
14621496 elif state == self .CMIS_STATE_AP_CONF :
14631497 # TODO: Use fine grained time when the CMIS memory map is available
14641498 if not self .check_module_state (api , ['ModuleReady' ]):
@@ -1494,8 +1528,14 @@ def task_worker(self):
14941528 self .force_cmis_reinit (lport , retries + 1 )
14951529 continue
14961530
1497- # TODO: Use fine grained time when the CMIS memory map is available
1498- self .port_dict [lport ]['cmis_expired' ] = now + datetime .timedelta (seconds = self .CMIS_DEF_EXPIRED )
1531+ if getattr (api , 'get_cmis_rev' , None ):
1532+ # Check datapath init pending on module that supports CMIS 5.x
1533+ majorRev = int (api .get_cmis_rev ().split ('.' )[0 ])
1534+ if majorRev >= 5 and not self .check_datapath_init_pending (api , host_lanes ):
1535+ self .log_notice ("{}: datapath init not pending" .format (lport ))
1536+ self .force_cmis_reinit (lport , retries + 1 )
1537+ continue
1538+
14991539 self .port_dict [lport ]['cmis_state' ] = self .CMIS_STATE_DP_INIT
15001540 elif state == self .CMIS_STATE_DP_INIT :
15011541 if not self .check_config_error (api , host_lanes , ['ConfigSuccess' ]):
@@ -1515,8 +1555,9 @@ def task_worker(self):
15151555
15161556 # D.1.3 Software Configuration and Initialization
15171557 api .set_datapath_init (host_lanes )
1518- # TODO: Use fine grained timeout when the CMIS memory map is available
1519- self .port_dict [lport ]['cmis_expired' ] = now + datetime .timedelta (seconds = self .CMIS_DEF_EXPIRED )
1558+ dpInitDuration = self .get_cmis_dp_init_duration_secs (api )
1559+ self .log_notice ("{} DpInit duration {} secs" .format (lport , dpInitDuration ))
1560+ self .port_dict [lport ]['cmis_expired' ] = now + datetime .timedelta (seconds = dpInitDuration )
15201561 self .port_dict [lport ]['cmis_state' ] = self .CMIS_STATE_DP_TXON
15211562 elif state == self .CMIS_STATE_DP_TXON :
15221563 if not self .check_datapath_state (api , host_lanes , ['DataPathInitialized' ]):
0 commit comments