📄 ci_lpmaint.c
字号:
* NOTE: The CI7B family of CI ports may report restoration of * port power without first reporting loss of it. This * occurs when power loss is detected and signaled by the * port, but its restoration is noticed before the initial * interrupt is even received and processed. In such cases * the appropriate interrupt service routine crashes the * local port with a reason code of SE_POWERUP, and * processing proceeds as it does for any other event. * Furthermore, the local port may always be immediately * re-initialized when the time comes to do so, because the * local port always has power unlike many instances when * the local port is crashed for power loss( * reason == SE_POWER ). * * Inputs: * * IPL_SCS - Interrupt processor level * ci_lpc_panic - CI local port crash panic flag * ci_max_reinits - CI max number consecutive reinitializations * pccb - Port Command and Control Block pointer * reason - Reason for crashing local CI port * scsbp - Address of SCS header in optional buffer * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * forkb - PCCB fork block * lpinfo.reason - Reason for port failure * pd.gvp.type.ci - CI specific PCCB fields * reinit_tries - Number consecutive re-initializations left * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.cleanup - 1 * fsmstatus.fkip - 1 * fsmstatus.online - 0 * * SMP: The PCCB is locked INTERNALLY whenever it was not locked * EXTERNALLY prior to routine invocation. Locking the PCCB * allows exclusive access to PCCB contents and prevents * premature PB deletion. PCCB addresses are always valid because * these data structures are never deleted once their * corresponding ports have been initialized. */voidci_crash_lport( pccb, reason, scsbp ) register PCCB *pccb; register u_long reason; SCSH *scsbp;{ register PB *pb; register GVPH *cibp; u_long port_state; register u_long log_regs = LOG_NOREGS, unlock = 0; /* Crashing a local CI port consists of a number of distinct steps: * * 1. The crash request is pre-processed. * 2. The local port is disabled. * 3. The local port is cleaned up. * 4. The local port is re-initialized. * * The first step is executed each time this routine is invoked. It is the * latter three steps which constitute crashing the port and are executed * only once per port incarnation. The major benefits of this single * threading of port crashing are the assumptions made during port clean up * and re-initialization which follow directly from it. These assumptions * greatly reduce code complexity and allow extension of the CI port driver * to an SMP environment with a minimum of pain. They are pointed out as * they occur. * * Pre-processing of crash requests includes: * * 1. Locking the PCCB whenever it was not locked EXTERNALLY. * 2. Retrieving the appropriate PB whenever an optional buffer was * provided. * 3. Applying the local port crash severity modifier( ESM_LPC ) to the * local port crash reason code. * 4. Logging the crash request according to the provided crash reason. * 5. Optionally panicing the system. * 6. Deallocating the optional buffer. * * The local port crash severity modifier is applied( Step 3 ) ONLY if the * local port is not already in the process of being crashed. * * Panicing of the system( Step 5 ) immediately terminates all further * processing of the crash request. Such panicing is OPTIONAL. It is * requested only when the CI configuration variable flag ci_lpc_panic is * set. This flag is set only when special debugging activity is required. * * Following pre-processing this routine ascertains whether or not the port * has already been crashed but not yet re-initialized. If this is indeed * the case, as indicated by a PCCB clean up in progress status flag, then * the current request is dismissed after the PCCB is unlocked( provided it * was unlocked within this routine ). Otherwise, actual crashing of the * port commences with disablement of the local port including: * * 1. Setting the port clean up in progress flag to prohibit additional * crashings of the port until it has been re-initialized. * 2. Taking the port offline. * 3. Ascertaining the port state from the crash reason. Note, it is only * necessary to ascertain whether the port is currently enabled or not. * 4. Disabling interrupts on the port( enabled ports only ). * 5. Gracefully shutting down the port to abort all commands currently * undergoing processing( enabled ports only ). * 6. Disabling the port adapter in a hardware port type specific fashion. * 7. Resetting bus specific register contents( CIBCI/CIBCA/CIXCD only ). * 8. Disabling the port maintenance timer. * * Two additional actions are taken whenever the local port has lost power( * CI750/CI780/CIBCI only ) or is marked broken and is to be permanently * shutdown. These two actions constitute unmapping of the local port. * * 9. Unmapping the adapter I/O space system PTEs to a black hole page to * prevent stray machine checks. * 10. Changing the interrupt service handler for the local port to a * special routine( ci_unmapped_isr()) for fielding of all future * interrupts while the adapter I/O space is unmapped. * * The first few steps of local port disablement( Steps 1-3 ) are executed * by this routine. The remaining steps( Steps 4-10 ) are accomplished * through indirect invocation of the appropriate CI family specific * local CI port disablement routine. * * At the time the decision is made to crash the port, the processor from * which the port is crashed exists in one of two states distinguished * mainly by whether the processor is at kernel mode or interrupt level. * The existence of these two possible environments does not interfere with * port disablement. Unfortunately, the same is not necessary true for * port clean up, a section of the port driver which is quite complicated * in its own right. Therefore, to avoid potential problems and to allow * certain code simplifying assumptions to be made, port clean up has been * structured into two stages, separated by both time and environment. * * The first stage of port clean up consists of those actions which should * be performed immediately following port disablement and are insensitive * to processor state. The second stage consists of those activities which * need not be performed immediately following port disablement and should * be executed within a constant well-defined processor state. The first * stage of port clean up is directed by this routine which then schedules * the second stage, directed by ci_cleanup_port(), through forking. It is * this act of forking which generates the constant environment necessary * for the second stage of port clean up. * * The PCCB fork block is used to schedule the second stage of clean up. * It should always be available because it is used only for port clean up * and re-initialization, these activities are single threaded, and * re-initialization always follows clean up. Guaranteed availability * of the PCCB fork block is one of the benefits of single threading of * port clean up and re-initialization. * * The first stage of port clean up includes: * * 1. Scheduling clean up of the CI port through forking. * 2. Unlocking the PCCB provided it was locked within this routine. * * Note that the first stage of port clean up currently does not contain * any processor state insensitive actions which must be immediately * performed following port disablement. However, the structure exists to * add them as it becomes necessary to do so. * * The second stage of port clean up includes: * * 1. Locking the PCCB. * 2. Removing and deallocating all packets logged out to the datagram and * message buffer logout areas. CI ports logout all internalized queue * entries to the appropriate area only when power failure is detected. * 3. Unlocking the PCCB. * 4. Notifying the CI PPD of failure of the local port. * * The CI PPD completes the clean up of its portion of the local port * including the failure and clean up all paths, both formative and fully * established, originating at the port. Clean up of the last path * triggers scheduling of port re-initialization by the CI PPD. Successful * completion of port re-initialization marks the beginning of the next * incarnation of the port and releases all restriction on crashing the * port if further requests to do so are made. */ if( !Test_pccb_lock( pccb )) { Lock_pccb( pccb ) unlock = 1; } if( scsbp ) { cibp = Scs_to_pd( scsbp, pccb ); pb = cippd_get_pb( pccb, scsbp, BUF ); } else { pb = NULL; cibp = NULL; } if( !pccb->Fsmstatus.cleanup ) { Set_lpc_event( reason ); } switch( Mask_esevmod( reason )) { case SE_POWER: case SE_POWERUP: case SE_ICMDQ0: case SE_ICMDQ1: case SE_ICMDQ2: case SE_ICMDQ3: case SE_IDFREEQ: case SE_IMFREEQ: case SE_RRSPQ: case SE_RDFREEQ: case SE_RMFREEQ: case SE_MSE: case SE_BIMSE: case SE_DSE: case SE_PARITY: case SE_BIPARITY: case SE_PORTERROR: case SE_BIERROR: case SE_MFQE: case SE_SANITYTIMER: case FE_NOCI: case FE_BADMAXPORT: case FE_PORTERROR: log_regs = LOG_REGS; case FE_BADUCODE: ( void )ci_log_dev_attn( pccb, reason, log_regs ); break; case SE_PPDSANITY: case SE_NOPATH: case SE_INVLPKTSIZE: case SE_INVBNAME: case SE_INVBSIZE: case SE_BACCVIO: case SE_INVDPORT: case SE_UNKCMD: case SE_ABORTPKT: case SE_UNKSTATUS: case SE_UNKOPCODE: case SE_INVOPCODE: case SE_INVPA: case SE_INVSN: case SE_INVDDL: case SE_IRESVCD: case SE_IRESEQ: case SE_DISCVCPKT: ( void )ci_log_packet( pccb, pb, cibp, reason, LPORT_EVENT ); break; default: ( void )panic( PANIC_UNKLPC ); } if( ci_lpc_panic ) { ( void )panic( PANIC_REQLPC ); } else if( cibp ) { ( void )ci_dealloc_pkt( cibp ); } if( !pccb->Fsmstatus.cleanup ) { pccb->Fsmstatus.cleanup = 1; pccb->Fsmstatus.online = 0; pccb->Reinit_tries = ci_max_reinits; switch( Mask_esevmod( reason )) { case SE_POWER: case SE_POWERUP: case SE_MSE: case SE_BIMSE: case SE_DSE: case SE_PARITY: case SE_BIPARITY: case SE_PORTERROR: case SE_BIERROR: case SE_SANITYTIMER: case FE_NOCI: case FE_PORTERROR: port_state = PS_UNINIT; break; default: port_state = PS_ENAB; } ( void )( *pccb->Disable_port )( pccb, port_state ); pccb->lpinfo.reason = reason; Pccb_fork( pccb, ci_cleanup_port, PANIC_PCCBFB ) } if( unlock ) { Unlock_pccb( pccb ) }}/* Name: ci_remote_reset - Reset Remote Port and System * * Abstract: This function initiates resetting of a remote CI port and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -