2009-09-24 04:46:15 +04:00
/*
2015-11-26 11:54:45 +03:00
* Copyright ( c ) 2005 - 2014 Brocade Communications Systems , Inc .
* Copyright ( c ) 2014 - QLogic Corporation .
2009-09-24 04:46:15 +04:00
* All rights reserved
2015-11-26 11:54:45 +03:00
* www . qlogic . com
2009-09-24 04:46:15 +04:00
*
2015-11-26 11:54:46 +03:00
* Linux driver for QLogic BR - series Fibre Channel Host Bus Adapter .
2009-09-24 04:46:15 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License ( GPL ) Version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*/
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* fcpim . c - FCP initiator mode i - t nexus state machine
*/
2010-12-10 06:12:32 +03:00
# include "bfad_drv.h"
2010-09-15 22:50:55 +04:00
# include "bfa_fcs.h"
# include "bfa_fcbuild.h"
# include "bfad_im.h"
2009-09-24 04:46:15 +04:00
BFA_TRC_FILE ( FCS , FCPIM ) ;
/*
* forward declarations
*/
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_timeout ( void * arg ) ;
static void bfa_fcs_itnim_free ( struct bfa_fcs_itnim_s * itnim ) ;
static void bfa_fcs_itnim_send_prli ( void * itnim_cbarg ,
2009-09-24 04:46:15 +04:00
struct bfa_fcxp_s * fcxp_alloced ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_prli_response ( void * fcsarg ,
struct bfa_fcxp_s * fcxp , void * cbarg ,
bfa_status_t req_status , u32 rsp_len ,
u32 resid_len , struct fchs_s * rsp_fchs ) ;
2011-07-21 03:59:13 +04:00
static void bfa_fcs_itnim_aen_post ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_itnim_aen_event event ) ;
2009-09-24 04:46:15 +04:00
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_offline ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_prli_send ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_prli ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_prli_retry ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_hcb_online ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2012-08-23 06:52:58 +04:00
static void bfa_fcs_itnim_sm_hal_rport_online ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_online ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_hcb_offline ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
2010-09-15 22:50:55 +04:00
static void bfa_fcs_itnim_sm_initiator ( struct bfa_fcs_itnim_s * itnim ,
2009-09-24 04:46:15 +04:00
enum bfa_fcs_itnim_event event ) ;
static struct bfa_sm_table_s itnim_sm_table [ ] = {
{ BFA_SM ( bfa_fcs_itnim_sm_offline ) , BFA_ITNIM_OFFLINE } ,
{ BFA_SM ( bfa_fcs_itnim_sm_prli_send ) , BFA_ITNIM_PRLI_SEND } ,
{ BFA_SM ( bfa_fcs_itnim_sm_prli ) , BFA_ITNIM_PRLI_SENT } ,
{ BFA_SM ( bfa_fcs_itnim_sm_prli_retry ) , BFA_ITNIM_PRLI_RETRY } ,
{ BFA_SM ( bfa_fcs_itnim_sm_hcb_online ) , BFA_ITNIM_HCB_ONLINE } ,
{ BFA_SM ( bfa_fcs_itnim_sm_online ) , BFA_ITNIM_ONLINE } ,
{ BFA_SM ( bfa_fcs_itnim_sm_hcb_offline ) , BFA_ITNIM_HCB_OFFLINE } ,
{ BFA_SM ( bfa_fcs_itnim_sm_initiator ) , BFA_ITNIM_INITIATIOR } ,
} ;
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* fcs_itnim_sm FCS itnim state machine
*/
static void
bfa_fcs_itnim_sm_offline ( struct bfa_fcs_itnim_s * itnim ,
2010-09-15 22:50:55 +04:00
enum bfa_fcs_itnim_event event )
2009-09-24 04:46:15 +04:00
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
2012-08-23 06:52:58 +04:00
case BFA_FCS_ITNIM_SM_FCS_ONLINE :
2009-09-24 04:46:15 +04:00
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_prli_send ) ;
2010-07-09 06:52:00 +04:00
itnim - > prli_retries = 0 ;
2009-09-24 04:46:15 +04:00
bfa_fcs_itnim_send_prli ( itnim , NULL ) ;
break ;
case BFA_FCS_ITNIM_SM_OFFLINE :
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_INITIATOR :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_initiator ) ;
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
static void
bfa_fcs_itnim_sm_prli_send ( struct bfa_fcs_itnim_s * itnim ,
2010-09-15 22:50:55 +04:00
enum bfa_fcs_itnim_event event )
2009-09-24 04:46:15 +04:00
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_FRMSENT :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_prli ) ;
break ;
case BFA_FCS_ITNIM_SM_INITIATOR :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_initiator ) ;
bfa_fcxp_walloc_cancel ( itnim - > fcs - > bfa , & itnim - > fcxp_wqe ) ;
2012-08-23 06:52:58 +04:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_FCS_ONLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcxp_walloc_cancel ( itnim - > fcs - > bfa , & itnim - > fcxp_wqe ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcxp_walloc_cancel ( itnim - > fcs - > bfa , & itnim - > fcxp_wqe ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
static void
bfa_fcs_itnim_sm_prli ( struct bfa_fcs_itnim_s * itnim ,
2010-09-15 22:50:55 +04:00
enum bfa_fcs_itnim_event event )
2009-09-24 04:46:15 +04:00
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_RSP_OK :
2012-08-23 06:52:58 +04:00
if ( itnim - > rport - > scsi_function = = BFA_RPORT_INITIATOR )
2010-07-09 06:55:41 +04:00
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_initiator ) ;
2012-08-23 06:52:58 +04:00
else
bfa_sm_set_state ( itnim ,
bfa_fcs_itnim_sm_hal_rport_online ) ;
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_FCS_ONLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_RSP_ERROR :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_prli_retry ) ;
bfa_timer_start ( itnim - > fcs - > bfa , & itnim - > timer ,
bfa_fcs_itnim_timeout , itnim ,
BFA_FCS_RETRY_TIMEOUT ) ;
break ;
2011-06-25 07:24:52 +04:00
case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
break ;
2009-09-24 04:46:15 +04:00
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcxp_discard ( itnim - > fcxp ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_INITIATOR :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_initiator ) ;
2010-07-09 06:55:41 +04:00
bfa_fcxp_discard ( itnim - > fcxp ) ;
2012-08-23 06:52:58 +04:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_FCS_ONLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcxp_discard ( itnim - > fcxp ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
2012-08-23 06:52:58 +04:00
static void
bfa_fcs_itnim_sm_hal_rport_online ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_fcs_itnim_event event )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_HAL_ONLINE :
if ( ! itnim - > bfa_itnim )
itnim - > bfa_itnim = bfa_itnim_create ( itnim - > fcs - > bfa ,
itnim - > rport - > bfa_rport , itnim ) ;
if ( itnim - > bfa_itnim ) {
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_hcb_online ) ;
bfa_itnim_online ( itnim - > bfa_itnim , itnim - > seq_rec ) ;
} else {
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_DELETE ) ;
}
break ;
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
bfa_sm_fault ( itnim - > fcs , event ) ;
}
}
2009-09-24 04:46:15 +04:00
static void
bfa_fcs_itnim_sm_prli_retry ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_fcs_itnim_event event )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_TIMEOUT :
2010-07-09 06:52:00 +04:00
if ( itnim - > prli_retries < BFA_FCS_RPORT_MAX_RETRIES ) {
itnim - > prli_retries + + ;
bfa_trc ( itnim - > fcs , itnim - > prli_retries ) ;
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_prli_send ) ;
bfa_fcs_itnim_send_prli ( itnim , NULL ) ;
} else {
/* invoke target offline */
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_LOGO_IMP ) ;
2010-07-09 06:52:00 +04:00
}
2009-09-24 04:46:15 +04:00
break ;
2010-09-15 22:50:55 +04:00
2009-09-24 04:46:15 +04:00
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_timer_stop ( & itnim - > timer ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_INITIATOR :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_initiator ) ;
bfa_timer_stop ( & itnim - > timer ) ;
2012-08-23 06:52:58 +04:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_FCS_ONLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_timer_stop ( & itnim - > timer ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
static void
bfa_fcs_itnim_sm_hcb_online ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_fcs_itnim_event event )
{
2010-09-15 22:50:55 +04:00
struct bfad_s * bfad = ( struct bfad_s * ) itnim - > fcs - > bfad ;
char lpwwn_buf [ BFA_STRING_32 ] ;
char rpwwn_buf [ BFA_STRING_32 ] ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_HCB_ONLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_online ) ;
bfa_fcb_itnim_online ( itnim - > itnim_drv ) ;
2010-09-15 22:50:55 +04:00
wwn2str ( lpwwn_buf , bfa_fcs_lport_get_pwwn ( itnim - > rport - > port ) ) ;
wwn2str ( rpwwn_buf , itnim - > rport - > pwwn ) ;
2010-12-10 04:11:53 +03:00
BFA_LOG ( KERN_INFO , bfad , bfa_log_level ,
2010-09-15 22:50:55 +04:00
" Target (WWN = %s) is online for initiator (WWN = %s) \n " ,
rpwwn_buf , lpwwn_buf ) ;
2011-07-21 03:59:13 +04:00
bfa_fcs_itnim_aen_post ( itnim , BFA_ITNIM_AEN_ONLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_OFFLINE :
2012-08-23 06:52:58 +04:00
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_hcb_offline ) ;
2009-09-24 04:46:15 +04:00
bfa_itnim_offline ( itnim - > bfa_itnim ) ;
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
static void
bfa_fcs_itnim_sm_online ( struct bfa_fcs_itnim_s * itnim ,
2010-09-15 22:50:55 +04:00
enum bfa_fcs_itnim_event event )
2009-09-24 04:46:15 +04:00
{
2010-09-15 22:50:55 +04:00
struct bfad_s * bfad = ( struct bfad_s * ) itnim - > fcs - > bfad ;
char lpwwn_buf [ BFA_STRING_32 ] ;
char rpwwn_buf [ BFA_STRING_32 ] ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_hcb_offline ) ;
bfa_fcb_itnim_offline ( itnim - > itnim_drv ) ;
bfa_itnim_offline ( itnim - > bfa_itnim ) ;
2010-09-15 22:50:55 +04:00
wwn2str ( lpwwn_buf , bfa_fcs_lport_get_pwwn ( itnim - > rport - > port ) ) ;
wwn2str ( rpwwn_buf , itnim - > rport - > pwwn ) ;
2011-07-21 03:59:13 +04:00
if ( bfa_fcs_lport_is_online ( itnim - > rport - > port ) = = BFA_TRUE ) {
2010-12-10 04:11:53 +03:00
BFA_LOG ( KERN_ERR , bfad , bfa_log_level ,
2010-09-15 22:50:55 +04:00
" Target (WWN = %s) connectivity lost for "
" initiator (WWN = %s) \n " , rpwwn_buf , lpwwn_buf ) ;
2011-07-21 03:59:13 +04:00
bfa_fcs_itnim_aen_post ( itnim , BFA_ITNIM_AEN_DISCONNECT ) ;
} else {
2010-12-10 04:11:53 +03:00
BFA_LOG ( KERN_INFO , bfad , bfa_log_level ,
2010-09-15 22:50:55 +04:00
" Target (WWN = %s) offlined by initiator (WWN = %s) \n " ,
rpwwn_buf , lpwwn_buf ) ;
2011-07-21 03:59:13 +04:00
bfa_fcs_itnim_aen_post ( itnim , BFA_ITNIM_AEN_OFFLINE ) ;
}
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
static void
bfa_fcs_itnim_sm_hcb_offline ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_fcs_itnim_event event )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_HCB_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
/*
* This state is set when a discovered rport is also in intiator mode .
* This ITN is marked as no_op and is not active and will not be truned into
* online state .
*/
static void
bfa_fcs_itnim_sm_initiator ( struct bfa_fcs_itnim_s * itnim ,
2010-09-15 22:50:55 +04:00
enum bfa_fcs_itnim_event event )
2009-09-24 04:46:15 +04:00
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_trc ( itnim - > fcs , event ) ;
switch ( event ) {
case BFA_FCS_ITNIM_SM_OFFLINE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_OFFLINE ) ;
2009-09-24 04:46:15 +04:00
break ;
2012-08-23 06:52:58 +04:00
/*
* fcs_online is expected here for well known initiator ports
*/
case BFA_FCS_ITNIM_SM_FCS_ONLINE :
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_FC4_FCS_ONLINE ) ;
break ;
2009-09-24 04:46:15 +04:00
case BFA_FCS_ITNIM_SM_RSP_ERROR :
case BFA_FCS_ITNIM_SM_INITIATOR :
break ;
case BFA_FCS_ITNIM_SM_DELETE :
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
bfa_fcs_itnim_free ( itnim ) ;
break ;
default :
2010-03-06 06:35:02 +03:00
bfa_sm_fault ( itnim - > fcs , event ) ;
2009-09-24 04:46:15 +04:00
}
}
2011-07-21 03:59:13 +04:00
static void
bfa_fcs_itnim_aen_post ( struct bfa_fcs_itnim_s * itnim ,
enum bfa_itnim_aen_event event )
{
struct bfa_fcs_rport_s * rport = itnim - > rport ;
struct bfad_s * bfad = ( struct bfad_s * ) itnim - > fcs - > bfad ;
struct bfa_aen_entry_s * aen_entry ;
/* Don't post events for well known addresses */
if ( BFA_FCS_PID_IS_WKA ( rport - > pid ) )
return ;
bfad_get_aen_entry ( bfad , aen_entry ) ;
if ( ! aen_entry )
return ;
aen_entry - > aen_data . itnim . vf_id = rport - > port - > fabric - > vf_id ;
aen_entry - > aen_data . itnim . ppwwn = bfa_fcs_lport_get_pwwn (
bfa_fcs_get_base_port ( itnim - > fcs ) ) ;
aen_entry - > aen_data . itnim . lpwwn = bfa_fcs_lport_get_pwwn ( rport - > port ) ;
aen_entry - > aen_data . itnim . rpwwn = rport - > pwwn ;
/* Send the AEN notification */
bfad_im_post_vendor_event ( aen_entry , bfad , + + rport - > fcs - > fcs_aen_seq ,
BFA_AEN_CAT_ITNIM , event ) ;
}
2009-09-24 04:46:15 +04:00
static void
bfa_fcs_itnim_send_prli ( void * itnim_cbarg , struct bfa_fcxp_s * fcxp_alloced )
{
struct bfa_fcs_itnim_s * itnim = itnim_cbarg ;
struct bfa_fcs_rport_s * rport = itnim - > rport ;
2010-09-15 22:50:55 +04:00
struct bfa_fcs_lport_s * port = rport - > port ;
struct fchs_s fchs ;
2009-09-24 04:46:15 +04:00
struct bfa_fcxp_s * fcxp ;
2010-09-15 22:50:55 +04:00
int len ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
2012-08-23 06:51:08 +04:00
fcxp = fcxp_alloced ? fcxp_alloced :
bfa_fcs_fcxp_alloc ( port - > fcs , BFA_TRUE ) ;
2009-09-24 04:46:15 +04:00
if ( ! fcxp ) {
itnim - > stats . fcxp_alloc_wait + + ;
2010-09-15 22:50:55 +04:00
bfa_fcs_fcxp_alloc_wait ( port - > fcs - > bfa , & itnim - > fcxp_wqe ,
2012-08-23 06:51:08 +04:00
bfa_fcs_itnim_send_prli , itnim , BFA_TRUE ) ;
2009-09-24 04:46:15 +04:00
return ;
}
itnim - > fcxp = fcxp ;
2010-09-15 22:50:55 +04:00
len = fc_prli_build ( & fchs , bfa_fcxp_get_reqbuf ( fcxp ) ,
itnim - > rport - > pid , bfa_fcs_lport_get_fcid ( port ) , 0 ) ;
2009-09-24 04:46:15 +04:00
bfa_fcxp_send ( fcxp , rport - > bfa_rport , port - > fabric - > vf_id , port - > lp_tag ,
BFA_FALSE , FC_CLASS_3 , len , & fchs ,
2010-09-15 22:50:55 +04:00
bfa_fcs_itnim_prli_response , ( void * ) itnim ,
FC_MAX_PDUSZ , FC_ELS_TOV ) ;
2009-09-24 04:46:15 +04:00
itnim - > stats . prli_sent + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_FRMSENT ) ;
}
static void
bfa_fcs_itnim_prli_response ( void * fcsarg , struct bfa_fcxp_s * fcxp , void * cbarg ,
bfa_status_t req_status , u32 rsp_len ,
u32 resid_len , struct fchs_s * rsp_fchs )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cbarg ;
struct fc_els_cmd_s * els_cmd ;
struct fc_prli_s * prli_resp ;
struct fc_ls_rjt_s * ls_rjt ;
2009-09-24 04:46:15 +04:00
struct fc_prli_params_s * sparams ;
bfa_trc ( itnim - > fcs , req_status ) ;
/*
* Sanity Checks
*/
if ( req_status ! = BFA_STATUS_OK ) {
itnim - > stats . prli_rsp_err + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_RSP_ERROR ) ;
return ;
}
els_cmd = ( struct fc_els_cmd_s * ) BFA_FCXP_RSP_PLD ( fcxp ) ;
if ( els_cmd - > els_code = = FC_ELS_ACC ) {
prli_resp = ( struct fc_prli_s * ) els_cmd ;
if ( fc_prli_rsp_parse ( prli_resp , rsp_len ) ! = FC_PARSE_OK ) {
bfa_trc ( itnim - > fcs , rsp_len ) ;
/*
* Check if this r - port is also in Initiator mode .
* If so , we need to set this ITN as a no - op .
*/
if ( prli_resp - > parampage . servparams . initiator ) {
bfa_trc ( itnim - > fcs , prli_resp - > parampage . type ) ;
itnim - > rport - > scsi_function =
2012-08-23 06:52:58 +04:00
BFA_RPORT_INITIATOR ;
2009-09-24 04:46:15 +04:00
itnim - > stats . prli_rsp_acc + + ;
2011-06-25 07:24:52 +04:00
itnim - > stats . initiator + + ;
2009-09-24 04:46:15 +04:00
bfa_sm_send_event ( itnim ,
2010-07-09 06:55:41 +04:00
BFA_FCS_ITNIM_SM_RSP_OK ) ;
2009-09-24 04:46:15 +04:00
return ;
}
itnim - > stats . prli_rsp_parse_err + + ;
return ;
}
itnim - > rport - > scsi_function = BFA_RPORT_TARGET ;
sparams = & prli_resp - > parampage . servparams ;
2010-09-15 22:50:55 +04:00
itnim - > seq_rec = sparams - > retry ;
itnim - > rec_support = sparams - > rec_support ;
2009-09-24 04:46:15 +04:00
itnim - > task_retry_id = sparams - > task_retry_id ;
2010-09-15 22:50:55 +04:00
itnim - > conf_comp = sparams - > confirm ;
2009-09-24 04:46:15 +04:00
itnim - > stats . prli_rsp_acc + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_RSP_OK ) ;
} else {
ls_rjt = ( struct fc_ls_rjt_s * ) BFA_FCXP_RSP_PLD ( fcxp ) ;
bfa_trc ( itnim - > fcs , ls_rjt - > reason_code ) ;
bfa_trc ( itnim - > fcs , ls_rjt - > reason_code_expl ) ;
itnim - > stats . prli_rsp_rjt + + ;
2011-06-25 07:24:52 +04:00
if ( ls_rjt - > reason_code = = FC_LS_RJT_RSN_CMD_NOT_SUPP ) {
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_RSP_NOT_SUPP ) ;
return ;
}
2009-09-24 04:46:15 +04:00
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_RSP_ERROR ) ;
}
}
static void
bfa_fcs_itnim_timeout ( void * arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) arg ;
2009-09-24 04:46:15 +04:00
itnim - > stats . timeout + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_TIMEOUT ) ;
}
static void
bfa_fcs_itnim_free ( struct bfa_fcs_itnim_s * itnim )
{
2012-08-23 06:52:58 +04:00
if ( itnim - > bfa_itnim ) {
bfa_itnim_delete ( itnim - > bfa_itnim ) ;
itnim - > bfa_itnim = NULL ;
}
2009-09-24 04:46:15 +04:00
bfa_fcb_itnim_free ( itnim - > fcs - > bfad , itnim - > itnim_drv ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* itnim_public FCS ITNIM public interfaces
*/
2010-10-19 04:17:23 +04:00
/*
2010-09-15 22:50:55 +04:00
* Called by rport when a new rport is created .
2009-09-24 04:46:15 +04:00
*
* @ param [ in ] rport - remote port .
*/
struct bfa_fcs_itnim_s *
bfa_fcs_itnim_create ( struct bfa_fcs_rport_s * rport )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_lport_s * port = rport - > port ;
2009-09-24 04:46:15 +04:00
struct bfa_fcs_itnim_s * itnim ;
2010-09-15 22:50:55 +04:00
struct bfad_itnim_s * itnim_drv ;
2016-04-13 14:14:41 +03:00
int ret ;
2009-09-24 04:46:15 +04:00
/*
* call bfad to allocate the itnim
*/
2016-04-13 14:14:41 +03:00
ret = bfa_fcb_itnim_alloc ( port - > fcs - > bfad , & itnim , & itnim_drv ) ;
if ( ret ) {
2009-09-24 04:46:15 +04:00
bfa_trc ( port - > fcs , rport - > pwwn ) ;
return NULL ;
}
/*
* Initialize itnim
*/
itnim - > rport = rport ;
itnim - > fcs = rport - > fcs ;
itnim - > itnim_drv = itnim_drv ;
2012-08-23 06:52:58 +04:00
itnim - > bfa_itnim = NULL ;
2010-09-15 22:50:55 +04:00
itnim - > seq_rec = BFA_FALSE ;
itnim - > rec_support = BFA_FALSE ;
itnim - > conf_comp = BFA_FALSE ;
2009-09-24 04:46:15 +04:00
itnim - > task_retry_id = BFA_FALSE ;
/*
* Set State machine
*/
bfa_sm_set_state ( itnim , bfa_fcs_itnim_sm_offline ) ;
return itnim ;
}
2010-10-19 04:17:23 +04:00
/*
2010-09-15 22:50:55 +04:00
* Called by rport to delete the instance of FCPIM .
2009-09-24 04:46:15 +04:00
*
* @ param [ in ] rport - remote port .
*/
void
bfa_fcs_itnim_delete ( struct bfa_fcs_itnim_s * itnim )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pid ) ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_DELETE ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Notification from rport that PLOGI is complete to initiate FC - 4 session .
*/
void
2012-08-23 06:52:58 +04:00
bfa_fcs_itnim_brp_online ( struct bfa_fcs_itnim_s * itnim )
2009-09-24 04:46:15 +04:00
{
itnim - > stats . onlines + + ;
2012-08-23 06:52:58 +04:00
if ( ! BFA_FCS_PID_IS_WKA ( itnim - > rport - > pid ) )
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_HAL_ONLINE ) ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Called by rport to handle a remote device offline .
*/
void
bfa_fcs_itnim_rport_offline ( struct bfa_fcs_itnim_s * itnim )
{
itnim - > stats . offlines + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_OFFLINE ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Called by rport when remote port is known to be an initiator from
* PRLI received .
*/
void
bfa_fcs_itnim_is_initiator ( struct bfa_fcs_itnim_s * itnim )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pid ) ;
itnim - > stats . initiator + + ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_INITIATOR ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Called by rport to check if the itnim is online .
*/
bfa_status_t
bfa_fcs_itnim_get_online_state ( struct bfa_fcs_itnim_s * itnim )
{
bfa_trc ( itnim - > fcs , itnim - > rport - > pid ) ;
switch ( bfa_sm_to_state ( itnim_sm_table , itnim - > sm ) ) {
case BFA_ITNIM_ONLINE :
case BFA_ITNIM_INITIATIOR :
return BFA_STATUS_OK ;
default :
return BFA_STATUS_NO_FCPIM_NEXUS ;
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* BFA completion callback for bfa_itnim_online ( ) .
*/
void
bfa_cb_itnim_online ( void * cbarg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cbarg ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_HCB_ONLINE ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* BFA completion callback for bfa_itnim_offline ( ) .
*/
void
bfa_cb_itnim_offline ( void * cb_arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cb_arg ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
bfa_sm_send_event ( itnim , BFA_FCS_ITNIM_SM_HCB_OFFLINE ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Mark the beginning of PATH TOV handling . IO completion callbacks
* are still pending .
*/
void
bfa_cb_itnim_tov_begin ( void * cb_arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cb_arg ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* Mark the end of PATH TOV handling . All pending IOs are already cleaned up .
*/
void
bfa_cb_itnim_tov ( void * cb_arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cb_arg ;
struct bfad_itnim_s * itnim_drv = itnim - > itnim_drv ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
2010-09-15 22:50:55 +04:00
itnim_drv - > state = ITNIM_STATE_TIMEOUT ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2010-09-15 22:50:55 +04:00
* BFA notification to FCS / driver for second level error recovery .
2009-09-24 04:46:15 +04:00
*
* Atleast one I / O request has timedout and target is unresponsive to
* repeated abort requests . Second level error recovery should be initiated
* by starting implicit logout and recovery procedures .
*/
void
bfa_cb_itnim_sler ( void * cb_arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_fcs_itnim_s * itnim = ( struct bfa_fcs_itnim_s * ) cb_arg ;
2009-09-24 04:46:15 +04:00
itnim - > stats . sler + + ;
bfa_trc ( itnim - > fcs , itnim - > rport - > pwwn ) ;
2010-12-10 06:08:43 +03:00
bfa_sm_send_event ( itnim - > rport , RPSM_EVENT_LOGO_IMP ) ;
2009-09-24 04:46:15 +04:00
}
struct bfa_fcs_itnim_s *
2010-09-15 22:50:55 +04:00
bfa_fcs_itnim_lookup ( struct bfa_fcs_lport_s * port , wwn_t rpwwn )
2009-09-24 04:46:15 +04:00
{
struct bfa_fcs_rport_s * rport ;
rport = bfa_fcs_rport_lookup ( port , rpwwn ) ;
if ( ! rport )
return NULL ;
2010-12-27 08:46:35 +03:00
WARN_ON ( rport - > itnim = = NULL ) ;
2009-09-25 23:29:54 +04:00
return rport - > itnim ;
2009-09-24 04:46:15 +04:00
}
bfa_status_t
2010-09-15 22:50:55 +04:00
bfa_fcs_itnim_attr_get ( struct bfa_fcs_lport_s * port , wwn_t rpwwn ,
2009-09-24 04:46:15 +04:00
struct bfa_itnim_attr_s * attr )
{
struct bfa_fcs_itnim_s * itnim = NULL ;
itnim = bfa_fcs_itnim_lookup ( port , rpwwn ) ;
if ( itnim = = NULL )
return BFA_STATUS_NO_FCPIM_NEXUS ;
2010-09-15 22:50:55 +04:00
attr - > state = bfa_sm_to_state ( itnim_sm_table , itnim - > sm ) ;
attr - > retry = itnim - > seq_rec ;
attr - > rec_support = itnim - > rec_support ;
attr - > conf_comp = itnim - > conf_comp ;
2009-09-24 04:46:15 +04:00
attr - > task_retry_id = itnim - > task_retry_id ;
return BFA_STATUS_OK ;
}
bfa_status_t
2010-09-15 22:50:55 +04:00
bfa_fcs_itnim_stats_get ( struct bfa_fcs_lport_s * port , wwn_t rpwwn ,
2009-09-24 04:46:15 +04:00
struct bfa_itnim_stats_s * stats )
{
struct bfa_fcs_itnim_s * itnim = NULL ;
2010-12-27 08:46:35 +03:00
WARN_ON ( port = = NULL ) ;
2009-09-24 04:46:15 +04:00
itnim = bfa_fcs_itnim_lookup ( port , rpwwn ) ;
if ( itnim = = NULL )
return BFA_STATUS_NO_FCPIM_NEXUS ;
2010-10-19 04:08:54 +04:00
memcpy ( stats , & itnim - > stats , sizeof ( struct bfa_itnim_stats_s ) ) ;
2009-09-24 04:46:15 +04:00
return BFA_STATUS_OK ;
}
bfa_status_t
2010-09-15 22:50:55 +04:00
bfa_fcs_itnim_stats_clear ( struct bfa_fcs_lport_s * port , wwn_t rpwwn )
2009-09-24 04:46:15 +04:00
{
struct bfa_fcs_itnim_s * itnim = NULL ;
2010-12-27 08:46:35 +03:00
WARN_ON ( port = = NULL ) ;
2009-09-24 04:46:15 +04:00
itnim = bfa_fcs_itnim_lookup ( port , rpwwn ) ;
if ( itnim = = NULL )
return BFA_STATUS_NO_FCPIM_NEXUS ;
2010-10-19 04:08:54 +04:00
memset ( & itnim - > stats , 0 , sizeof ( struct bfa_itnim_stats_s ) ) ;
2009-09-24 04:46:15 +04:00
return BFA_STATUS_OK ;
}
void
2010-09-15 22:50:55 +04:00
bfa_fcs_fcpim_uf_recv ( struct bfa_fcs_itnim_s * itnim ,
struct fchs_s * fchs , u16 len )
2009-09-24 04:46:15 +04:00
{
2010-09-15 22:50:55 +04:00
struct fc_els_cmd_s * els_cmd ;
2009-09-24 04:46:15 +04:00
bfa_trc ( itnim - > fcs , fchs - > type ) ;
if ( fchs - > type ! = FC_TYPE_ELS )
return ;
els_cmd = ( struct fc_els_cmd_s * ) ( fchs + 1 ) ;
bfa_trc ( itnim - > fcs , els_cmd - > els_code ) ;
switch ( els_cmd - > els_code ) {
case FC_ELS_PRLO :
2010-07-09 06:55:41 +04:00
bfa_fcs_rport_prlo ( itnim - > rport , fchs - > ox_id ) ;
2009-09-24 04:46:15 +04:00
break ;
default :
2010-12-27 08:46:35 +03:00
WARN_ON ( 1 ) ;
2009-09-24 04:46:15 +04:00
}
}