2021-06-23 22:25:56 -07:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell Fibre Channel HBA Driver
* Copyright ( c ) 2021 Marvell
*/
# include "qla_def.h"
# include "qla_edif.h"
# include <linux/kthread.h>
# include <linux/vmalloc.h>
# include <linux/delay.h>
# include <scsi/scsi_tcq.h>
2021-06-23 22:26:00 -07:00
static struct edif_sa_index_entry * qla_edif_sadb_find_sa_index_entry ( uint16_t nport_handle ,
struct list_head * sa_list ) ;
static uint16_t qla_edif_sadb_get_sa_index ( fc_port_t * fcport ,
struct qla_sa_update_frame * sa_frame ) ;
static int qla_edif_sadb_delete_sa_index ( fc_port_t * fcport , uint16_t nport_handle ,
uint16_t sa_index ) ;
2021-06-23 22:25:58 -07:00
static int qla_pur_get_pending ( scsi_qla_host_t * , fc_port_t * , struct bsg_job * ) ;
2021-06-23 22:26:03 -07:00
struct edb_node {
struct list_head list ;
uint32_t ntype ;
union {
port_id_t plogi_did ;
uint32_t async ;
port_id_t els_sid ;
struct edif_sa_update_aen sa_aen ;
} u ;
} ;
2021-06-23 22:25:58 -07:00
static struct els_sub_cmd {
uint16_t cmd ;
const char * str ;
} sc_str [ ] = {
{ SEND_ELS , " send ELS " } ,
{ SEND_ELS_REPLY , " send ELS Reply " } ,
{ PULL_ELS , " retrieve ELS " } ,
} ;
const char * sc_to_str ( uint16_t cmd )
{
int i ;
struct els_sub_cmd * e ;
for ( i = 0 ; i < ARRAY_SIZE ( sc_str ) ; i + + ) {
e = sc_str + i ;
if ( cmd = = e - > cmd )
return e - > str ;
}
return " unknown " ;
}
2022-06-06 21:46:20 -07:00
static struct edb_node * qla_edb_getnext ( scsi_qla_host_t * vha )
{
unsigned long flags ;
struct edb_node * edbnode = NULL ;
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
/* db nodes are fifo - no qualifications done */
if ( ! list_empty ( & vha - > e_dbell . head ) ) {
edbnode = list_first_entry ( & vha - > e_dbell . head ,
struct edb_node , list ) ;
list_del_init ( & edbnode - > list ) ;
}
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
return edbnode ;
}
static void qla_edb_node_free ( scsi_qla_host_t * vha , struct edb_node * node )
{
list_del_init ( & node - > list ) ;
kfree ( node ) ;
}
2021-06-23 22:26:00 -07:00
static struct edif_list_entry * qla_edif_list_find_sa_index ( fc_port_t * fcport ,
uint16_t handle )
{
struct edif_list_entry * entry ;
struct edif_list_entry * tentry ;
struct list_head * indx_list = & fcport - > edif . edif_indx_list ;
list_for_each_entry_safe ( entry , tentry , indx_list , next ) {
if ( entry - > handle = = handle )
return entry ;
}
return NULL ;
}
/* timeout called when no traffic and delayed rx sa_index delete */
static void qla2x00_sa_replace_iocb_timeout ( struct timer_list * t )
{
struct edif_list_entry * edif_entry = from_timer ( edif_entry , t , timer ) ;
fc_port_t * fcport = edif_entry - > fcport ;
struct scsi_qla_host * vha = fcport - > vha ;
struct edif_sa_ctl * sa_ctl ;
uint16_t nport_handle ;
unsigned long flags = 0 ;
ql_dbg ( ql_dbg_edif , vha , 0x3069 ,
" %s: nport_handle 0x%x, SA REPL Delay Timeout, %8phC portid=%06x \n " ,
__func__ , edif_entry - > handle , fcport - > port_name , fcport - > d_id . b24 ) ;
/*
* if delete_sa_index is valid then no one has serviced this
* delayed delete
*/
spin_lock_irqsave ( & fcport - > edif . indx_list_lock , flags ) ;
/*
* delete_sa_index is invalidated when we find the new sa_index in
* the incoming data stream . If it is not invalidated then we are
* still looking for the new sa_index because there is no I / O and we
* need to just force the rx delete and move on . Otherwise
* we could get another rekey which will result in an error 66.
*/
if ( edif_entry - > delete_sa_index ! = INVALID_EDIF_SA_INDEX ) {
uint16_t delete_sa_index = edif_entry - > delete_sa_index ;
edif_entry - > delete_sa_index = INVALID_EDIF_SA_INDEX ;
nport_handle = edif_entry - > handle ;
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
sa_ctl = qla_edif_find_sa_ctl_by_index ( fcport ,
delete_sa_index , 0 ) ;
if ( sa_ctl ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sa_ctl: %p, delete index %d, update index: %d, lid: 0x%x \n " ,
__func__ , sa_ctl , delete_sa_index , edif_entry - > update_sa_index ,
nport_handle ) ;
sa_ctl - > flags = EDIF_SA_CTL_FLG_DEL ;
set_bit ( EDIF_SA_CTL_REPL , & sa_ctl - > state ) ;
qla_post_sa_replace_work ( fcport - > vha , fcport ,
nport_handle , sa_ctl ) ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sa_ctl not found for delete_sa_index: %d \n " ,
__func__ , edif_entry - > delete_sa_index ) ;
}
} else {
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
}
}
/*
* create a new list entry for this nport handle and
* add an sa_update index to the list - called for sa_update
*/
static int qla_edif_list_add_sa_update_index ( fc_port_t * fcport ,
uint16_t sa_index , uint16_t handle )
{
struct edif_list_entry * entry ;
unsigned long flags = 0 ;
/* if the entry exists, then just update the sa_index */
entry = qla_edif_list_find_sa_index ( fcport , handle ) ;
if ( entry ) {
entry - > update_sa_index = sa_index ;
entry - > count = 0 ;
return 0 ;
}
/*
* This is the normal path - there should be no existing entry
* when update is called . The exception is at startup
* when update is called for the first two sa_indexes
* followed by a delete of the first sa_index
*/
entry = kzalloc ( ( sizeof ( struct edif_list_entry ) ) , GFP_ATOMIC ) ;
if ( ! entry )
return - ENOMEM ;
INIT_LIST_HEAD ( & entry - > next ) ;
entry - > handle = handle ;
entry - > update_sa_index = sa_index ;
entry - > delete_sa_index = INVALID_EDIF_SA_INDEX ;
entry - > count = 0 ;
entry - > flags = 0 ;
timer_setup ( & entry - > timer , qla2x00_sa_replace_iocb_timeout , 0 ) ;
spin_lock_irqsave ( & fcport - > edif . indx_list_lock , flags ) ;
list_add_tail ( & entry - > next , & fcport - > edif . edif_indx_list ) ;
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
return 0 ;
}
/* remove an entry from the list */
static void qla_edif_list_delete_sa_index ( fc_port_t * fcport , struct edif_list_entry * entry )
{
unsigned long flags = 0 ;
spin_lock_irqsave ( & fcport - > edif . indx_list_lock , flags ) ;
list_del ( & entry - > next ) ;
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
}
int qla_post_sa_replace_work ( struct scsi_qla_host * vha ,
fc_port_t * fcport , uint16_t nport_handle , struct edif_sa_ctl * sa_ctl )
{
struct qla_work_evt * e ;
e = qla2x00_alloc_work ( vha , QLA_EVT_SA_REPLACE ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . sa_update . fcport = fcport ;
e - > u . sa_update . sa_ctl = sa_ctl ;
e - > u . sa_update . nport_handle = nport_handle ;
fcport - > flags | = FCF_ASYNC_ACTIVE ;
return qla2x00_post_work ( vha , e ) ;
}
2021-06-23 22:25:56 -07:00
static void
qla_edif_sa_ctl_init ( scsi_qla_host_t * vha , struct fc_port * fcport )
{
ql_dbg ( ql_dbg_edif , vha , 0x2058 ,
2021-06-23 22:26:00 -07:00
" Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%06x. \n " ,
fcport - > node_name , fcport - > port_name , fcport - > d_id . b24 ) ;
2021-06-23 22:25:56 -07:00
fcport - > edif . tx_rekey_cnt = 0 ;
fcport - > edif . rx_rekey_cnt = 0 ;
fcport - > edif . tx_bytes = 0 ;
fcport - > edif . rx_bytes = 0 ;
}
2021-06-23 22:25:58 -07:00
static int qla_bsg_check ( scsi_qla_host_t * vha , struct bsg_job * bsg_job ,
fc_port_t * fcport )
{
struct extra_auth_els * p ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct qla_bsg_auth_els_request * req =
( struct qla_bsg_auth_els_request * ) bsg_job - > request ;
if ( ! vha - > hw - > flags . edif_enabled ) {
ql_dbg ( ql_dbg_edif , vha , 0x9105 ,
" %s edif not enabled \n " , __func__ ) ;
goto done ;
}
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:25:58 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s doorbell not enabled \n " , __func__ ) ;
goto done ;
}
p = & req - > e ;
/* Get response */
if ( p - > sub_cmd = = PULL_ELS ) {
struct qla_bsg_auth_els_reply * rpl =
( struct qla_bsg_auth_els_reply * ) bsg_job - > reply ;
qla_pur_get_pending ( vha , fcport , bsg_job ) ;
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s %s %8phN sid=%x. xchg %x, nb=%xh bsg ptr %p \n " ,
__func__ , sc_to_str ( p - > sub_cmd ) , fcport - > port_name ,
fcport - > d_id . b24 , rpl - > rx_xchg_address ,
rpl - > r . reply_payload_rcv_len , bsg_job ) ;
goto done ;
}
return 0 ;
done :
bsg_job_done ( bsg_job , bsg_reply - > result ,
bsg_reply - > reply_payload_rcv_len ) ;
return - EIO ;
}
fc_port_t *
qla2x00_find_fcport_by_pid ( scsi_qla_host_t * vha , port_id_t * id )
{
fc_port_t * f , * tf ;
f = NULL ;
list_for_each_entry_safe ( f , tf , & vha - > vp_fcports , list ) {
2022-06-06 21:46:19 -07:00
if ( f - > d_id . b24 = = id - > b24 )
return f ;
2021-06-23 22:25:58 -07:00
}
return NULL ;
}
2021-06-23 22:25:56 -07:00
/**
* qla_edif_app_check ( ) : check for valid application id .
* @ vha : host adapter pointer
* @ appid : application id
* Return : false = fail , true = pass
*/
static bool
qla_edif_app_check ( scsi_qla_host_t * vha , struct app_id appid )
{
/* check that the app is allow/known to the driver */
2022-06-06 21:46:18 -07:00
if ( appid . app_vid ! = EDIF_APP_ID ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s app id not ok (%x) " ,
__func__ , appid . app_vid ) ;
return false ;
}
if ( appid . version ! = EDIF_VERSION1 ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s app version is not ok (%x) " ,
__func__ , appid . version ) ;
return false ;
2021-06-23 22:25:56 -07:00
}
2022-06-06 21:46:18 -07:00
return true ;
2021-06-23 22:25:56 -07:00
}
2021-06-23 22:26:00 -07:00
static void
qla_edif_free_sa_ctl ( fc_port_t * fcport , struct edif_sa_ctl * sa_ctl ,
int index )
{
unsigned long flags = 0 ;
spin_lock_irqsave ( & fcport - > edif . sa_list_lock , flags ) ;
list_del ( & sa_ctl - > next ) ;
spin_unlock_irqrestore ( & fcport - > edif . sa_list_lock , flags ) ;
if ( index > = 512 )
fcport - > edif . tx_rekey_cnt - - ;
else
fcport - > edif . rx_rekey_cnt - - ;
kfree ( sa_ctl ) ;
}
/* return an index to the freepool */
static void qla_edif_add_sa_index_to_freepool ( fc_port_t * fcport , int dir ,
uint16_t sa_index )
{
void * sa_id_map ;
struct scsi_qla_host * vha = fcport - > vha ;
struct qla_hw_data * ha = vha - > hw ;
unsigned long flags = 0 ;
u16 lsa_index = sa_index ;
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x3063 ,
" %s: entry \n " , __func__ ) ;
if ( dir ) {
sa_id_map = ha - > edif_tx_sa_id_map ;
lsa_index - = EDIF_TX_SA_INDEX_BASE ;
} else {
sa_id_map = ha - > edif_rx_sa_id_map ;
}
spin_lock_irqsave ( & ha - > sadb_fp_lock , flags ) ;
clear_bit ( lsa_index , sa_id_map ) ;
spin_unlock_irqrestore ( & ha - > sadb_fp_lock , flags ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: index %d added to free pool \n " , __func__ , sa_index ) ;
}
static void __qla2x00_release_all_sadb ( struct scsi_qla_host * vha ,
struct fc_port * fcport , struct edif_sa_index_entry * entry ,
int pdir )
{
struct edif_list_entry * edif_entry ;
struct edif_sa_ctl * sa_ctl ;
int i , dir ;
int key_cnt = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
if ( entry - > sa_pair [ i ] . sa_index = = INVALID_EDIF_SA_INDEX )
continue ;
if ( fcport - > loop_id ! = entry - > handle ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: ** WARNING %d** entry handle: 0x%x, lid: 0x%x, sa_index: %d \n " ,
__func__ , i , entry - > handle , fcport - > loop_id ,
entry - > sa_pair [ i ] . sa_index ) ;
}
/* release the sa_ctl */
sa_ctl = qla_edif_find_sa_ctl_by_index ( fcport ,
entry - > sa_pair [ i ] . sa_index , pdir ) ;
if ( sa_ctl & &
qla_edif_find_sa_ctl_by_index ( fcport , sa_ctl - > index , pdir ) ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_ctl for index %d \n " , __func__ , sa_ctl - > index ) ;
qla_edif_free_sa_ctl ( fcport , sa_ctl , sa_ctl - > index ) ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sa_ctl NOT freed, sa_ctl: %p \n " , __func__ , sa_ctl ) ;
}
/* Release the index */
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_index %d, nph: 0x%x \n " ,
__func__ , entry - > sa_pair [ i ] . sa_index , entry - > handle ) ;
dir = ( entry - > sa_pair [ i ] . sa_index <
EDIF_TX_SA_INDEX_BASE ) ? 0 : 1 ;
qla_edif_add_sa_index_to_freepool ( fcport , dir ,
entry - > sa_pair [ i ] . sa_index ) ;
/* Delete timer on RX */
if ( pdir ! = SAU_FLG_TX ) {
edif_entry =
qla_edif_list_find_sa_index ( fcport , entry - > handle ) ;
if ( edif_entry ) {
ql_dbg ( ql_dbg_edif , vha , 0x5033 ,
" %s: remove edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x \n " ,
__func__ , edif_entry , edif_entry - > update_sa_index ,
edif_entry - > delete_sa_index ) ;
qla_edif_list_delete_sa_index ( fcport , edif_entry ) ;
/*
* valid delete_sa_index indicates there is a rx
* delayed delete queued
*/
if ( edif_entry - > delete_sa_index ! =
INVALID_EDIF_SA_INDEX ) {
2022-12-20 13:45:19 -05:00
timer_shutdown ( & edif_entry - > timer ) ;
2021-06-23 22:26:00 -07:00
/* build and send the aen */
fcport - > edif . rx_sa_set = 1 ;
fcport - > edif . rx_sa_pending = 0 ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( vha ,
VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
QL_VND_SA_STAT_SUCCESS ,
QL_VND_RX_SA_KEY , fcport ) ;
2021-06-23 22:26:00 -07:00
}
ql_dbg ( ql_dbg_edif , vha , 0x5033 ,
" %s: release edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x \n " ,
__func__ , edif_entry , edif_entry - > update_sa_index ,
edif_entry - > delete_sa_index ) ;
kfree ( edif_entry ) ;
}
}
key_cnt + + ;
}
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: %d %s keys released \n " ,
__func__ , key_cnt , pdir ? " tx " : " rx " ) ;
}
/* find an release all outstanding sadb sa_indicies */
void qla2x00_release_all_sadb ( struct scsi_qla_host * vha , struct fc_port * fcport )
{
struct edif_sa_index_entry * entry , * tmp ;
struct qla_hw_data * ha = vha - > hw ;
unsigned long flags ;
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x3063 ,
" %s: Starting... \n " , __func__ ) ;
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
list_for_each_entry_safe ( entry , tmp , & ha - > sadb_rx_index_list , next ) {
if ( entry - > fcport = = fcport ) {
list_del ( & entry - > next ) ;
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
__qla2x00_release_all_sadb ( vha , fcport , entry , 0 ) ;
kfree ( entry ) ;
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
break ;
}
}
list_for_each_entry_safe ( entry , tmp , & ha - > sadb_tx_index_list , next ) {
if ( entry - > fcport = = fcport ) {
list_del ( & entry - > next ) ;
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
__qla2x00_release_all_sadb ( vha , fcport , entry , SAU_FLG_TX ) ;
kfree ( entry ) ;
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
break ;
}
}
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
}
2022-12-21 20:39:29 -08:00
/**
* qla_delete_n2n_sess_and_wait : search for N2N session , tear it down and
* wait for tear down to complete . In N2N topology , there is only one
* session being active in tracking the remote device .
* @ vha : host adapter pointer
* return code : 0 - found the session and completed the tear down .
* 1 - timeout occurred . Caller to use link bounce to reset .
*/
static int qla_delete_n2n_sess_and_wait ( scsi_qla_host_t * vha )
{
struct fc_port * fcport ;
int rc = - EIO ;
ulong expire = jiffies + 23 * HZ ;
if ( ! N2N_TOPO ( vha - > hw ) )
return 0 ;
fcport = NULL ;
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
if ( ! fcport - > n2n_flag )
continue ;
ql_dbg ( ql_dbg_disc , fcport - > vha , 0x2016 ,
" %s reset sess at app start \n " , __func__ ) ;
qla_edif_sa_ctl_init ( vha , fcport ) ;
qlt_schedule_sess_for_deletion ( fcport ) ;
while ( time_before_eq ( jiffies , expire ) ) {
if ( fcport - > disc_state ! = DSC_DELETE_PEND ) {
rc = 0 ;
break ;
}
msleep ( 1 ) ;
}
set_bit ( RELOGIN_NEEDED , & vha - > dpc_flags ) ;
break ;
}
return rc ;
}
2021-06-23 22:25:56 -07:00
/**
* qla_edif_app_start : application has announce its present
* @ vha : host adapter pointer
* @ bsg_job : user request
*
* Set / activate doorbell . Reset current sessions and re - login with
* secure flag .
*/
static int
qla_edif_app_start ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
int32_t rval = 0 ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct app_start appstart ;
struct app_start_reply appreply ;
struct fc_port * fcport , * tf ;
2021-10-26 04:54:03 -07:00
ql_log ( ql_log_info , vha , 0x1313 ,
" EDIF application registration with driver, FC device connections will be re-established. \n " ) ;
2021-06-23 22:25:56 -07:00
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & appstart ,
sizeof ( struct app_start ) ) ;
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s app_vid=%x app_start_flags %x \n " ,
__func__ , appstart . app_info . app_vid , appstart . app_start_flags ) ;
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:25:56 -07:00
/* mark doorbell as active since an app is now present */
2021-10-26 04:54:10 -07:00
vha - > e_dbell . db_flags | = EDB_ACTIVE ;
2021-06-23 22:25:56 -07:00
} else {
2022-06-08 04:58:42 -07:00
goto out ;
2021-06-23 22:25:56 -07:00
}
2021-08-16 22:13:08 -07:00
if ( N2N_TOPO ( vha - > hw ) ) {
2022-06-06 21:46:25 -07:00
list_for_each_entry_safe ( fcport , tf , & vha - > vp_fcports , list )
fcport - > n2n_link_reset_cnt = 0 ;
2022-06-08 04:58:47 -07:00
if ( vha - > hw - > flags . n2n_fw_acc_sec ) {
2022-12-21 20:39:29 -08:00
bool link_bounce = false ;
2022-06-08 04:58:47 -07:00
/*
* While authentication app was not running , remote device
* could still try to login with this local port . Let ' s
2022-12-21 20:39:29 -08:00
* reset the session , reconnect and re - authenticate .
2022-06-08 04:58:47 -07:00
*/
2022-12-21 20:39:29 -08:00
if ( qla_delete_n2n_sess_and_wait ( vha ) )
link_bounce = true ;
2022-06-08 04:58:47 -07:00
2022-12-21 20:39:29 -08:00
/* bounce the link to start login */
if ( ! vha - > hw - > flags . n2n_bigger | | link_bounce ) {
2022-06-08 04:58:47 -07:00
set_bit ( N2N_LINK_RESET , & vha - > dpc_flags ) ;
qla2xxx_wake_dpc ( vha ) ;
}
} else {
qla2x00_wait_for_hba_online ( vha ) ;
2021-08-16 22:13:08 -07:00
set_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) ;
2022-06-08 04:58:47 -07:00
qla2xxx_wake_dpc ( vha ) ;
qla2x00_wait_for_hba_online ( vha ) ;
}
2021-08-16 22:13:08 -07:00
} else {
list_for_each_entry_safe ( fcport , tf , & vha - > vp_fcports , list ) {
2021-10-26 04:54:03 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x2058 ,
" FCSP - nn %8phN pn %8phN portid=%06x. \n " ,
fcport - > node_name , fcport - > port_name ,
fcport - > d_id . b24 ) ;
2021-08-16 22:13:08 -07:00
ql_dbg ( ql_dbg_edif , vha , 0xf084 ,
2021-10-26 04:54:03 -07:00
" %s: se_sess %p / sess %p from port %8phC "
" loop_id %#04x s_id %06x logout %d "
" keep %d els_logo %d disc state %d auth state %d "
" stop state %d \n " ,
__func__ , fcport - > se_sess , fcport ,
fcport - > port_name , fcport - > loop_id ,
fcport - > d_id . b24 , fcport - > logout_on_delete ,
fcport - > keep_nport_handle , fcport - > send_els_logo ,
fcport - > disc_state , fcport - > edif . auth_state ,
fcport - > edif . app_stop ) ;
2021-06-23 22:25:56 -07:00
2021-08-16 22:13:08 -07:00
if ( atomic_read ( & vha - > loop_state ) = = LOOP_DOWN )
break ;
2021-06-23 22:25:56 -07:00
2021-10-26 04:54:03 -07:00
fcport - > login_retry = vha - > hw - > login_retry_count ;
fcport - > edif . app_stop = 0 ;
2022-06-06 21:46:17 -07:00
fcport - > edif . app_sess_online = 0 ;
if ( fcport - > scan_state ! = QLA_FCPORT_FOUND )
continue ;
if ( fcport - > port_type = = FCT_UNKNOWN & &
! fcport - > fc4_features )
rval = qla24xx_async_gffid ( vha , fcport , true ) ;
if ( ! rval & & ! ( fcport - > fc4_features & FC4_FF_TARGET | |
fcport - > port_type & ( FCT_TARGET | FCT_NVME_TARGET ) ) )
continue ;
rval = 0 ;
2021-10-26 04:54:03 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s wwpn %8phC calling qla_edif_reset_auth_wait \n " ,
__func__ , fcport - > port_name ) ;
2021-10-26 04:54:04 -07:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2021-08-16 22:13:08 -07:00
qla_edif_sa_ctl_init ( vha , fcport ) ;
}
2022-06-08 04:58:43 -07:00
set_bit ( RELOGIN_NEEDED , & vha - > dpc_flags ) ;
2021-06-23 22:25:56 -07:00
}
if ( vha - > pur_cinfo . enode_flags ! = ENODE_ACTIVE ) {
/* mark as active since an app is now present */
vha - > pur_cinfo . enode_flags = ENODE_ACTIVE ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x911f , " %s enode already active \n " ,
__func__ ) ;
}
2022-06-08 04:58:42 -07:00
out :
2021-06-23 22:25:56 -07:00
appreply . host_support_edif = vha - > hw - > flags . edif_enabled ;
appreply . edif_enode_active = vha - > pur_cinfo . enode_flags ;
appreply . edif_edb_active = vha - > e_dbell . db_flags ;
2022-06-06 21:46:18 -07:00
appreply . version = EDIF_VERSION1 ;
2021-06-23 22:25:56 -07:00
2021-10-26 04:54:11 -07:00
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
2021-06-23 22:25:56 -07:00
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
2021-10-26 04:54:11 -07:00
bsg_reply - > reply_payload_rcv_len = sg_copy_from_buffer ( bsg_job - > reply_payload . sg_list ,
bsg_job - > reply_payload . sg_cnt ,
& appreply ,
sizeof ( struct app_start_reply ) ) ;
2021-06-23 22:25:56 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s app start completed with 0x%x \n " ,
__func__ , rval ) ;
return rval ;
}
/**
* qla_edif_app_stop - app has announced it ' s exiting .
* @ vha : host adapter pointer
* @ bsg_job : user space command pointer
*
* Free any in flight messages , clear all doorbell events
* to application . Reject any message relate to security .
*/
static int
qla_edif_app_stop ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
struct app_stop appstop ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct fc_port * fcport , * tf ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & appstop ,
sizeof ( struct app_stop ) ) ;
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s Stopping APP: app_vid=%x \n " ,
__func__ , appstop . app_info . app_vid ) ;
/* Call db stop and enode stop functions */
/* if we leave this running short waits are operational < 16 secs */
qla_enode_stop ( vha ) ; /* stop enode */
qla_edb_stop ( vha ) ; /* stop db */
list_for_each_entry_safe ( fcport , tf , & vha - > vp_fcports , list ) {
2021-08-16 22:13:09 -07:00
if ( ! ( fcport - > flags & FCF_FCSP_DEVICE ) )
2021-06-23 22:25:56 -07:00
continue ;
if ( fcport - > flags & FCF_FCSP_DEVICE ) {
ql_dbg ( ql_dbg_edif , vha , 0xf084 ,
" %s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d \n " ,
__func__ , fcport ,
fcport - > port_name , fcport - > loop_id , fcport - > d_id . b24 ,
fcport - > logout_on_delete , fcport - > keep_nport_handle ,
fcport - > send_els_logo ) ;
if ( atomic_read ( & vha - > loop_state ) = = LOOP_DOWN )
break ;
fcport - > edif . app_stop = 1 ;
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s wwpn %8phC calling qla_edif_reset_auth_wait \n " ,
__func__ , fcport - > port_name ) ;
fcport - > send_els_logo = 1 ;
qlt_schedule_sess_for_deletion ( fcport ) ;
}
}
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
/* no return interface to app - it assumes we cleaned up ok */
2021-08-16 22:13:14 -07:00
return 0 ;
2021-06-23 22:25:56 -07:00
}
2021-06-23 22:26:01 -07:00
static int
qla_edif_app_chk_sa_update ( scsi_qla_host_t * vha , fc_port_t * fcport ,
struct app_plogi_reply * appplogireply )
{
int ret = 0 ;
if ( ! ( fcport - > edif . rx_sa_set & & fcport - > edif . tx_sa_set ) ) {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d. \n " ,
__func__ , fcport - > port_name , fcport - > edif . tx_sa_set ,
fcport - > edif . rx_sa_set ) ;
appplogireply - > prli_status = 0 ;
ret = 1 ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s wwpn %8phC Both SA(s) updated. \n " , __func__ ,
fcport - > port_name ) ;
fcport - > edif . rx_sa_set = fcport - > edif . tx_sa_set = 0 ;
fcport - > edif . rx_sa_pending = fcport - > edif . tx_sa_pending = 0 ;
appplogireply - > prli_status = 1 ;
}
return ret ;
}
/**
* qla_edif_app_authok - authentication by app succeeded . Driver can proceed
* with prli
* @ vha : host adapter pointer
* @ bsg_job : user request
*/
static int
qla_edif_app_authok ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
struct auth_complete_cmd appplogiok ;
struct app_plogi_reply appplogireply = { 0 } ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
fc_port_t * fcport = NULL ;
port_id_t portid = { 0 } ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & appplogiok ,
sizeof ( struct auth_complete_cmd ) ) ;
2022-01-09 21:02:13 -08:00
/* silent unaligned access warning */
portid . b . domain = appplogiok . u . d_id . b . domain ;
portid . b . area = appplogiok . u . d_id . b . area ;
portid . b . al_pa = appplogiok . u . d_id . b . al_pa ;
2022-06-06 21:46:18 -07:00
appplogireply . version = EDIF_VERSION1 ;
2021-06-23 22:26:01 -07:00
switch ( appplogiok . type ) {
case PL_TYPE_WWPN :
fcport = qla2x00_find_fcport_by_wwpn ( vha ,
appplogiok . u . wwpn , 0 ) ;
if ( ! fcport )
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s wwpn lookup failed: %8phC \n " ,
__func__ , appplogiok . u . wwpn ) ;
break ;
case PL_TYPE_DID :
2022-01-09 21:02:13 -08:00
fcport = qla2x00_find_fcport_by_pid ( vha , & portid ) ;
2021-06-23 22:26:01 -07:00
if ( ! fcport )
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s d_id lookup failed: %x \n " , __func__ ,
portid . b24 ) ;
break ;
default :
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s undefined type: %x \n " , __func__ ,
appplogiok . type ) ;
break ;
}
if ( ! fcport ) {
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto errstate_exit ;
}
/*
* if port is online then this is a REKEY operation
* Only do sa update checking
*/
if ( atomic_read ( & fcport - > state ) = = FCS_ONLINE ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s Skipping PRLI complete based on rekey \n " , __func__ ) ;
appplogireply . prli_status = 1 ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
qla_edif_app_chk_sa_update ( vha , fcport , & appplogireply ) ;
goto errstate_exit ;
}
/* make sure in AUTH_PENDING or else reject */
if ( fcport - > disc_state ! = DSC_LOGIN_AUTH_PEND ) {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s wwpn %8phC is not in auth pending state (%x) \n " ,
__func__ , fcport - > port_name , fcport - > disc_state ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
appplogireply . prli_status = 0 ;
goto errstate_exit ;
}
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
appplogireply . prli_status = 1 ;
2021-08-16 22:13:08 -07:00
fcport - > edif . authok = 1 ;
2021-06-23 22:26:01 -07:00
if ( ! ( fcport - > edif . rx_sa_set & & fcport - > edif . tx_sa_set ) ) {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d. \n " ,
__func__ , fcport - > port_name , fcport - > edif . tx_sa_set ,
fcport - > edif . rx_sa_set ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
appplogireply . prli_status = 0 ;
goto errstate_exit ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s wwpn %8phC Both SA(s) updated. \n " , __func__ ,
fcport - > port_name ) ;
fcport - > edif . rx_sa_set = fcport - > edif . tx_sa_set = 0 ;
fcport - > edif . rx_sa_pending = fcport - > edif . tx_sa_pending = 0 ;
}
if ( qla_ini_mode_enabled ( vha ) ) {
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s AUTH complete - RESUME with prli for wwpn %8phC \n " ,
__func__ , fcport - > port_name ) ;
qla24xx_post_prli_work ( vha , fcport ) ;
}
errstate_exit :
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
2021-10-26 04:54:11 -07:00
bsg_reply - > reply_payload_rcv_len = sg_copy_from_buffer ( bsg_job - > reply_payload . sg_list ,
bsg_job - > reply_payload . sg_cnt ,
& appplogireply ,
sizeof ( struct app_plogi_reply ) ) ;
2021-06-23 22:26:01 -07:00
2022-04-26 15:43:34 +08:00
return 0 ;
2021-06-23 22:26:01 -07:00
}
/**
* qla_edif_app_authfail - authentication by app has failed . Driver is given
* notice to tear down current session .
* @ vha : host adapter pointer
* @ bsg_job : user request
*/
static int
qla_edif_app_authfail ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
int32_t rval = 0 ;
struct auth_complete_cmd appplogifail ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
fc_port_t * fcport = NULL ;
port_id_t portid = { 0 } ;
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s app auth fail \n " , __func__ ) ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & appplogifail ,
sizeof ( struct auth_complete_cmd ) ) ;
2022-01-09 21:02:13 -08:00
/* silent unaligned access warning */
portid . b . domain = appplogifail . u . d_id . b . domain ;
portid . b . area = appplogifail . u . d_id . b . area ;
portid . b . al_pa = appplogifail . u . d_id . b . al_pa ;
2021-06-23 22:26:01 -07:00
/*
* TODO : edif : app has failed this plogi . Inform driver to
* take any action ( if any ) .
*/
switch ( appplogifail . type ) {
case PL_TYPE_WWPN :
fcport = qla2x00_find_fcport_by_wwpn ( vha ,
appplogifail . u . wwpn , 0 ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
break ;
case PL_TYPE_DID :
2022-01-09 21:02:13 -08:00
fcport = qla2x00_find_fcport_by_pid ( vha , & portid ) ;
2021-06-23 22:26:01 -07:00
if ( ! fcport )
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s d_id lookup failed: %x \n " , __func__ ,
portid . b24 ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
break ;
default :
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s undefined type: %x \n " , __func__ ,
appplogifail . type ) ;
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
rval = - 1 ;
break ;
}
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s fcport is 0x%p \n " , __func__ , fcport ) ;
if ( fcport ) {
/* set/reset edif values and flags */
ql_dbg ( ql_dbg_edif , vha , 0x911e ,
" %s reset the auth process - %8phC, loopid=%x portid=%06x. \n " ,
__func__ , fcport - > port_name , fcport - > loop_id , fcport - > d_id . b24 ) ;
if ( qla_ini_mode_enabled ( fcport - > vha ) ) {
fcport - > send_els_logo = 1 ;
2021-10-26 04:54:04 -07:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2021-06-23 22:26:01 -07:00
}
}
return rval ;
}
2021-06-23 22:25:57 -07:00
/**
* qla_edif_app_getfcinfo - app would like to read session info ( wwpn , nportid ,
* [ initiator | target ] mode . It can specific session with specific nport id or
* all sessions .
* @ vha : host adapter pointer
* @ bsg_job : user request pointer
*/
static int
qla_edif_app_getfcinfo ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
int32_t rval = 0 ;
2021-10-26 04:54:11 -07:00
int32_t pcnt = 0 ;
2021-06-23 22:25:57 -07:00
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct app_pinfo_req app_req ;
struct app_pinfo_reply * app_reply ;
port_id_t tdid ;
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s app get fcinfo \n " , __func__ ) ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & app_req ,
sizeof ( struct app_pinfo_req ) ) ;
app_reply = kzalloc ( ( sizeof ( struct app_pinfo_reply ) +
2021-10-26 04:54:11 -07:00
sizeof ( struct app_pinfo ) * app_req . num_ports ) , GFP_KERNEL ) ;
2021-06-23 22:25:57 -07:00
if ( ! app_reply ) {
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
rval = - 1 ;
} else {
struct fc_port * fcport = NULL , * tf ;
2022-06-06 21:46:18 -07:00
app_reply - > version = EDIF_VERSION1 ;
2021-06-23 22:25:57 -07:00
list_for_each_entry_safe ( fcport , tf , & vha - > vp_fcports , list ) {
if ( ! ( fcport - > flags & FCF_FCSP_DEVICE ) )
continue ;
2022-12-21 20:39:31 -08:00
tdid . b . domain = app_req . remote_pid . domain ;
tdid . b . area = app_req . remote_pid . area ;
tdid . b . al_pa = app_req . remote_pid . al_pa ;
2021-06-23 22:25:57 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x2058 ,
2021-06-23 22:26:01 -07:00
" APP request entry - portid=%06x. \n " , tdid . b24 ) ;
2021-06-23 22:25:57 -07:00
/* Ran out of space */
2021-11-09 14:52:19 +03:00
if ( pcnt > = app_req . num_ports )
2021-06-23 22:25:57 -07:00
break ;
if ( tdid . b24 ! = 0 & & tdid . b24 ! = fcport - > d_id . b24 )
continue ;
2022-06-08 04:58:47 -07:00
if ( ! N2N_TOPO ( vha - > hw ) ) {
if ( fcport - > scan_state ! = QLA_FCPORT_FOUND )
continue ;
2022-06-06 21:46:17 -07:00
2022-06-08 04:58:47 -07:00
if ( fcport - > port_type = = FCT_UNKNOWN & &
! fcport - > fc4_features )
rval = qla24xx_async_gffid ( vha , fcport ,
true ) ;
2022-06-06 21:46:17 -07:00
2022-06-08 04:58:47 -07:00
if ( ! rval & &
! ( fcport - > fc4_features & FC4_FF_TARGET | |
fcport - > port_type &
( FCT_TARGET | FCT_NVME_TARGET ) ) )
continue ;
}
2022-06-06 21:46:17 -07:00
rval = 0 ;
2022-06-06 21:46:18 -07:00
app_reply - > ports [ pcnt ] . version = EDIF_VERSION1 ;
2021-06-23 22:25:57 -07:00
app_reply - > ports [ pcnt ] . remote_type =
VND_CMD_RTYPE_UNKNOWN ;
if ( fcport - > port_type & ( FCT_NVME_TARGET | FCT_TARGET ) )
app_reply - > ports [ pcnt ] . remote_type | =
VND_CMD_RTYPE_TARGET ;
if ( fcport - > port_type & ( FCT_NVME_INITIATOR | FCT_INITIATOR ) )
app_reply - > ports [ pcnt ] . remote_type | =
VND_CMD_RTYPE_INITIATOR ;
app_reply - > ports [ pcnt ] . remote_pid = fcport - > d_id ;
ql_dbg ( ql_dbg_edif , vha , 0x2058 ,
2021-08-16 22:13:08 -07:00
" Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%06x secure %d. \n " ,
fcport - > node_name , fcport - > port_name , pcnt ,
2021-08-16 22:13:09 -07:00
fcport - > d_id . b24 , fcport - > flags & FCF_FCSP_DEVICE ) ;
2021-06-23 22:25:57 -07:00
switch ( fcport - > edif . auth_state ) {
case VND_CMD_AUTH_STATE_ELS_RCVD :
if ( fcport - > disc_state = = DSC_LOGIN_AUTH_PEND ) {
fcport - > edif . auth_state = VND_CMD_AUTH_STATE_NEEDED ;
app_reply - > ports [ pcnt ] . auth_state =
VND_CMD_AUTH_STATE_NEEDED ;
} else {
app_reply - > ports [ pcnt ] . auth_state =
VND_CMD_AUTH_STATE_ELS_RCVD ;
}
break ;
default :
app_reply - > ports [ pcnt ] . auth_state = fcport - > edif . auth_state ;
break ;
}
memcpy ( app_reply - > ports [ pcnt ] . remote_wwpn ,
fcport - > port_name , 8 ) ;
app_reply - > ports [ pcnt ] . remote_state =
( atomic_read ( & fcport - > state ) = =
FCS_ONLINE ? 1 : 0 ) ;
pcnt + + ;
if ( tdid . b24 ! = 0 )
break ;
}
app_reply - > port_count = pcnt ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
}
2021-10-26 04:54:11 -07:00
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
bsg_reply - > reply_payload_rcv_len = sg_copy_from_buffer ( bsg_job - > reply_payload . sg_list ,
bsg_job - > reply_payload . sg_cnt ,
app_reply ,
sizeof ( struct app_pinfo_reply ) + sizeof ( struct app_pinfo ) * pcnt ) ;
2021-06-23 22:25:57 -07:00
kfree ( app_reply ) ;
return rval ;
}
/**
* qla_edif_app_getstats - app would like to read various statistics info
* @ vha : host adapter pointer
* @ bsg_job : user request
*/
static int32_t
qla_edif_app_getstats ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
int32_t rval = 0 ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
2021-10-26 04:54:11 -07:00
uint32_t size ;
2021-06-23 22:25:57 -07:00
struct app_sinfo_req app_req ;
struct app_stats_reply * app_reply ;
2021-10-26 04:54:11 -07:00
uint32_t pcnt = 0 ;
2021-06-23 22:25:57 -07:00
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & app_req ,
sizeof ( struct app_sinfo_req ) ) ;
if ( app_req . num_ports = = 0 ) {
ql_dbg ( ql_dbg_async , vha , 0x911d ,
" %s app did not indicate number of ports to return \n " ,
__func__ ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
rval = - 1 ;
}
size = sizeof ( struct app_stats_reply ) +
( sizeof ( struct app_sinfo ) * app_req . num_ports ) ;
app_reply = kzalloc ( size , GFP_KERNEL ) ;
if ( ! app_reply ) {
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
rval = - 1 ;
} else {
struct fc_port * fcport = NULL , * tf ;
2022-06-06 21:46:18 -07:00
app_reply - > version = EDIF_VERSION1 ;
2021-06-23 22:25:57 -07:00
list_for_each_entry_safe ( fcport , tf , & vha - > vp_fcports , list ) {
if ( fcport - > edif . enable ) {
if ( pcnt > app_req . num_ports )
break ;
app_reply - > elem [ pcnt ] . rekey_count =
fcport - > edif . rekey_cnt ;
app_reply - > elem [ pcnt ] . tx_bytes =
fcport - > edif . tx_bytes ;
app_reply - > elem [ pcnt ] . rx_bytes =
fcport - > edif . rx_bytes ;
memcpy ( app_reply - > elem [ pcnt ] . remote_wwpn ,
fcport - > port_name , 8 ) ;
pcnt + + ;
}
}
app_reply - > elem_count = pcnt ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
}
2021-10-26 04:54:11 -07:00
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
2021-06-23 22:25:57 -07:00
bsg_reply - > reply_payload_rcv_len =
sg_copy_from_buffer ( bsg_job - > reply_payload . sg_list ,
2021-10-26 04:54:11 -07:00
bsg_job - > reply_payload . sg_cnt , app_reply ,
sizeof ( struct app_stats_reply ) + ( sizeof ( struct app_sinfo ) * pcnt ) ) ;
2021-06-23 22:25:57 -07:00
kfree ( app_reply ) ;
return rval ;
}
2022-06-06 21:46:19 -07:00
static int32_t
qla_edif_ack ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
struct fc_port * fcport ;
struct aen_complete_cmd ack ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & ack , sizeof ( ack ) ) ;
ql_dbg ( ql_dbg_edif , vha , 0x70cf ,
" %s: %06x event_code %x \n " ,
__func__ , ack . port_id . b24 , ack . event_code ) ;
fcport = qla2x00_find_fcport_by_pid ( vha , & ack . port_id ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
if ( ! fcport ) {
ql_dbg ( ql_dbg_edif , vha , 0x70cf ,
" %s: unable to find fcport %06x \n " ,
__func__ , ack . port_id . b24 ) ;
return 0 ;
}
switch ( ack . event_code ) {
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN :
fcport - > edif . sess_down_acked = 1 ;
break ;
default :
break ;
}
return 0 ;
}
2022-06-06 21:46:20 -07:00
static int qla_edif_consume_dbell ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
u32 sg_skip , reply_payload_len ;
bool keep ;
struct edb_node * dbnode = NULL ;
struct edif_app_dbell ap ;
int dat_size = 0 ;
sg_skip = 0 ;
reply_payload_len = bsg_job - > reply_payload . payload_len ;
while ( ( reply_payload_len - sg_skip ) > = sizeof ( struct edb_node ) ) {
dbnode = qla_edb_getnext ( vha ) ;
if ( dbnode ) {
keep = true ;
dat_size = 0 ;
ap . event_code = dbnode - > ntype ;
switch ( dbnode - > ntype ) {
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN :
case VND_CMD_AUTH_STATE_NEEDED :
ap . port_id = dbnode - > u . plogi_did ;
dat_size + = sizeof ( ap . port_id ) ;
break ;
case VND_CMD_AUTH_STATE_ELS_RCVD :
ap . port_id = dbnode - > u . els_sid ;
dat_size + = sizeof ( ap . port_id ) ;
break ;
case VND_CMD_AUTH_STATE_SAUPDATE_COMPL :
ap . port_id = dbnode - > u . sa_aen . port_id ;
memcpy ( & ap . event_data , & dbnode - > u ,
sizeof ( struct edif_sa_update_aen ) ) ;
dat_size + = sizeof ( struct edif_sa_update_aen ) ;
break ;
default :
keep = false ;
ql_log ( ql_log_warn , vha , 0x09102 ,
" %s unknown DB type=%d %p \n " ,
__func__ , dbnode - > ntype , dbnode ) ;
break ;
}
ap . event_data_size = dat_size ;
/* 8 = sizeof(ap.event_code + ap.event_data_size) */
dat_size + = 8 ;
if ( keep )
sg_skip + = sg_copy_buffer ( bsg_job - > reply_payload . sg_list ,
bsg_job - > reply_payload . sg_cnt ,
& ap , dat_size , sg_skip , false ) ;
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s Doorbell consumed : type=%d %p \n " ,
__func__ , dbnode - > ntype , dbnode ) ;
kfree ( dbnode ) ;
} else {
break ;
}
}
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
bsg_reply - > reply_payload_rcv_len = sg_skip ;
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
return 0 ;
}
static void __qla_edif_dbell_bsg_done ( scsi_qla_host_t * vha , struct bsg_job * bsg_job ,
u32 delay )
{
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
/* small sleep for doorbell events to accumulate */
if ( delay )
msleep ( delay ) ;
qla_edif_consume_dbell ( vha , bsg_job ) ;
bsg_job_done ( bsg_job , bsg_reply - > result , bsg_reply - > reply_payload_rcv_len ) ;
}
static void qla_edif_dbell_bsg_done ( scsi_qla_host_t * vha )
{
unsigned long flags ;
struct bsg_job * prev_bsg_job = NULL ;
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
if ( vha - > e_dbell . dbell_bsg_job ) {
prev_bsg_job = vha - > e_dbell . dbell_bsg_job ;
vha - > e_dbell . dbell_bsg_job = NULL ;
}
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
if ( prev_bsg_job )
__qla_edif_dbell_bsg_done ( vha , prev_bsg_job , 0 ) ;
}
static int
qla_edif_dbell_bsg ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
unsigned long flags ;
bool return_bsg = false ;
/* flush previous dbell bsg */
qla_edif_dbell_bsg_done ( vha ) ;
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
if ( list_empty ( & vha - > e_dbell . head ) & & DBELL_ACTIVE ( vha ) ) {
/*
* when the next db event happens , bsg_job will return .
* Otherwise , timer will return it .
*/
vha - > e_dbell . dbell_bsg_job = bsg_job ;
vha - > e_dbell . bsg_expire = jiffies + 10 * HZ ;
} else {
return_bsg = true ;
}
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
if ( return_bsg )
__qla_edif_dbell_bsg_done ( vha , bsg_job , 1 ) ;
return 0 ;
}
2021-06-23 22:25:56 -07:00
int32_t
qla_edif_app_mgmt ( struct bsg_job * bsg_job )
{
struct fc_bsg_request * bsg_request = bsg_job - > request ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct Scsi_Host * host = fc_bsg_to_shost ( bsg_job ) ;
scsi_qla_host_t * vha = shost_priv ( host ) ;
struct app_id appcheck ;
bool done = true ;
int32_t rval = 0 ;
uint32_t vnd_sc = bsg_request - > rqst_data . h_vendor . vendor_cmd [ 1 ] ;
2022-06-06 21:46:20 -07:00
u32 level = ql_dbg_edif ;
2021-06-23 22:25:56 -07:00
2022-06-06 21:46:20 -07:00
/* doorbell is high traffic */
if ( vnd_sc = = QL_VND_SC_READ_DBELL )
level = 0 ;
ql_dbg ( level , vha , 0x911d , " %s vnd subcmd=%x \n " ,
2021-06-23 22:25:56 -07:00
__func__ , vnd_sc ) ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & appcheck ,
sizeof ( struct app_id ) ) ;
if ( ! vha - > hw - > flags . edif_enabled | |
test_bit ( VPORT_DELETE , & vha - > dpc_flags ) ) {
2022-06-06 21:46:20 -07:00
ql_dbg ( level , vha , 0x911d ,
2021-06-23 22:26:04 -07:00
" %s edif not enabled or vp delete. bsg ptr done %p. dpc_flags %lx \n " ,
__func__ , bsg_job , vha - > dpc_flags ) ;
2021-06-23 22:25:56 -07:00
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
}
if ( ! qla_edif_app_check ( vha , appcheck ) ) {
2022-06-06 21:46:20 -07:00
ql_dbg ( level , vha , 0x911d ,
2021-06-23 22:25:56 -07:00
" %s app checked failed. \n " ,
__func__ ) ;
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
}
switch ( vnd_sc ) {
2021-06-23 22:26:00 -07:00
case QL_VND_SC_SA_UPDATE :
done = false ;
rval = qla24xx_sadb_update ( bsg_job ) ;
break ;
2021-06-23 22:25:56 -07:00
case QL_VND_SC_APP_START :
rval = qla_edif_app_start ( vha , bsg_job ) ;
break ;
case QL_VND_SC_APP_STOP :
rval = qla_edif_app_stop ( vha , bsg_job ) ;
break ;
2021-06-23 22:26:01 -07:00
case QL_VND_SC_AUTH_OK :
rval = qla_edif_app_authok ( vha , bsg_job ) ;
break ;
case QL_VND_SC_AUTH_FAIL :
rval = qla_edif_app_authfail ( vha , bsg_job ) ;
break ;
2021-06-23 22:25:57 -07:00
case QL_VND_SC_GET_FCINFO :
rval = qla_edif_app_getfcinfo ( vha , bsg_job ) ;
break ;
case QL_VND_SC_GET_STATS :
rval = qla_edif_app_getstats ( vha , bsg_job ) ;
break ;
2022-06-06 21:46:19 -07:00
case QL_VND_SC_AEN_COMPLETE :
rval = qla_edif_ack ( vha , bsg_job ) ;
break ;
2022-06-06 21:46:20 -07:00
case QL_VND_SC_READ_DBELL :
rval = qla_edif_dbell_bsg ( vha , bsg_job ) ;
done = false ;
break ;
2021-06-23 22:25:56 -07:00
default :
ql_dbg ( ql_dbg_edif , vha , 0x911d , " %s unknown cmd=%x \n " ,
__func__ ,
bsg_request - > rqst_data . h_vendor . vendor_cmd [ 1 ] ) ;
rval = EXT_STATUS_INVALID_PARAM ;
2021-10-26 04:54:11 -07:00
done = false ;
2021-06-23 22:25:56 -07:00
break ;
}
done :
if ( done ) {
2022-06-06 21:46:20 -07:00
ql_dbg ( level , vha , 0x7009 ,
2021-06-23 22:25:56 -07:00
" %s: %d bsg ptr done %p \n " , __func__ , __LINE__ , bsg_job ) ;
bsg_job_done ( bsg_job , bsg_reply - > result ,
bsg_reply - > reply_payload_rcv_len ) ;
}
return rval ;
}
2021-06-23 22:26:00 -07:00
static struct edif_sa_ctl *
qla_edif_add_sa_ctl ( fc_port_t * fcport , struct qla_sa_update_frame * sa_frame ,
int dir )
{
struct edif_sa_ctl * sa_ctl ;
struct qla_sa_update_frame * sap ;
int index = sa_frame - > fast_sa_index ;
unsigned long flags = 0 ;
sa_ctl = kzalloc ( sizeof ( * sa_ctl ) , GFP_KERNEL ) ;
if ( ! sa_ctl ) {
/* couldn't get space */
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" unable to allocate SA CTL \n " ) ;
return NULL ;
}
/*
* need to allocate sa_index here and save it
* in both sa_ctl - > index and sa_frame - > fast_sa_index ;
* If alloc fails then delete sa_ctl and return NULL
*/
INIT_LIST_HEAD ( & sa_ctl - > next ) ;
sap = & sa_ctl - > sa_frame ;
* sap = * sa_frame ;
sa_ctl - > index = index ;
sa_ctl - > fcport = fcport ;
sa_ctl - > flags = 0 ;
sa_ctl - > state = 0L ;
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" %s: Added sa_ctl %p, index %d, state 0x%lx \n " ,
__func__ , sa_ctl , sa_ctl - > index , sa_ctl - > state ) ;
spin_lock_irqsave ( & fcport - > edif . sa_list_lock , flags ) ;
if ( dir = = SAU_FLG_TX )
list_add_tail ( & sa_ctl - > next , & fcport - > edif . tx_sa_list ) ;
else
list_add_tail ( & sa_ctl - > next , & fcport - > edif . rx_sa_list ) ;
spin_unlock_irqrestore ( & fcport - > edif . sa_list_lock , flags ) ;
return sa_ctl ;
}
void
qla_edif_flush_sa_ctl_lists ( fc_port_t * fcport )
{
struct edif_sa_ctl * sa_ctl , * tsa_ctl ;
unsigned long flags = 0 ;
spin_lock_irqsave ( & fcport - > edif . sa_list_lock , flags ) ;
list_for_each_entry_safe ( sa_ctl , tsa_ctl , & fcport - > edif . tx_sa_list ,
next ) {
list_del ( & sa_ctl - > next ) ;
kfree ( sa_ctl ) ;
}
list_for_each_entry_safe ( sa_ctl , tsa_ctl , & fcport - > edif . rx_sa_list ,
next ) {
list_del ( & sa_ctl - > next ) ;
kfree ( sa_ctl ) ;
}
spin_unlock_irqrestore ( & fcport - > edif . sa_list_lock , flags ) ;
}
struct edif_sa_ctl *
qla_edif_find_sa_ctl_by_index ( fc_port_t * fcport , int index , int dir )
{
struct edif_sa_ctl * sa_ctl , * tsa_ctl ;
struct list_head * sa_list ;
if ( dir = = SAU_FLG_TX )
sa_list = & fcport - > edif . tx_sa_list ;
else
sa_list = & fcport - > edif . rx_sa_list ;
list_for_each_entry_safe ( sa_ctl , tsa_ctl , sa_list , next ) {
if ( test_bit ( EDIF_SA_CTL_USED , & sa_ctl - > state ) & &
sa_ctl - > index = = index )
return sa_ctl ;
}
return NULL ;
}
/* add the sa to the correct list */
static int
qla24xx_check_sadb_avail_slot ( struct bsg_job * bsg_job , fc_port_t * fcport ,
struct qla_sa_update_frame * sa_frame )
{
struct edif_sa_ctl * sa_ctl = NULL ;
int dir ;
uint16_t sa_index ;
dir = ( sa_frame - > flags & SAU_FLG_TX ) ;
/* map the spi to an sa_index */
sa_index = qla_edif_sadb_get_sa_index ( fcport , sa_frame ) ;
if ( sa_index = = RX_DELETE_NO_EDIF_SA_INDEX ) {
/* process rx delete */
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x3063 ,
" %s: rx delete for lid 0x%x, spi 0x%x, no entry found \n " ,
__func__ , fcport - > loop_id , sa_frame - > spi ) ;
/* build and send the aen */
fcport - > edif . rx_sa_set = 1 ;
fcport - > edif . rx_sa_pending = 0 ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( fcport - > vha ,
VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
QL_VND_SA_STAT_SUCCESS ,
QL_VND_RX_SA_KEY , fcport ) ;
2021-06-23 22:26:00 -07:00
/* force a return of good bsg status; */
return RX_DELETE_NO_EDIF_SA_INDEX ;
} else if ( sa_index = = INVALID_EDIF_SA_INDEX ) {
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" %s: Failed to get sa_index for spi 0x%x, dir: %d \n " ,
__func__ , sa_frame - > spi , dir ) ;
return INVALID_EDIF_SA_INDEX ;
}
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" %s: index %d allocated to spi 0x%x, dir: %d, nport_handle: 0x%x \n " ,
__func__ , sa_index , sa_frame - > spi , dir , fcport - > loop_id ) ;
/* This is a local copy of sa_frame. */
sa_frame - > fast_sa_index = sa_index ;
/* create the sa_ctl */
sa_ctl = qla_edif_add_sa_ctl ( fcport , sa_frame , dir ) ;
if ( ! sa_ctl ) {
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" %s: Failed to add sa_ctl for spi 0x%x, dir: %d, sa_index: %d \n " ,
__func__ , sa_frame - > spi , dir , sa_index ) ;
return - 1 ;
}
set_bit ( EDIF_SA_CTL_USED , & sa_ctl - > state ) ;
if ( dir = = SAU_FLG_TX )
fcport - > edif . tx_rekey_cnt + + ;
else
fcport - > edif . rx_rekey_cnt + + ;
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x9100 ,
" %s: Found sa_ctl %p, index %d, state 0x%lx, tx_cnt %d, rx_cnt %d, nport_handle: 0x%x \n " ,
__func__ , sa_ctl , sa_ctl - > index , sa_ctl - > state ,
fcport - > edif . tx_rekey_cnt ,
fcport - > edif . rx_rekey_cnt , fcport - > loop_id ) ;
return 0 ;
}
# define QLA_SA_UPDATE_FLAGS_RX_KEY 0x0
# define QLA_SA_UPDATE_FLAGS_TX_KEY 0x2
2022-06-06 21:46:23 -07:00
# define EDIF_MSLEEP_INTERVAL 100
# define EDIF_RETRY_COUNT 50
2021-06-23 22:26:00 -07:00
int
qla24xx_sadb_update ( struct bsg_job * bsg_job )
{
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
struct Scsi_Host * host = fc_bsg_to_shost ( bsg_job ) ;
scsi_qla_host_t * vha = shost_priv ( host ) ;
fc_port_t * fcport = NULL ;
srb_t * sp = NULL ;
struct edif_list_entry * edif_entry = NULL ;
int found = 0 ;
int rval = 0 ;
2022-06-06 21:46:23 -07:00
int result = 0 , cnt ;
2021-06-23 22:26:00 -07:00
struct qla_sa_update_frame sa_frame ;
struct srb_iocb * iocb_cmd ;
2022-01-09 21:02:13 -08:00
port_id_t portid ;
2021-06-23 22:26:00 -07:00
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x911d ,
" %s entered, vha: 0x%p \n " , __func__ , vha ) ;
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , & sa_frame ,
sizeof ( struct qla_sa_update_frame ) ) ;
/* Check if host is online */
if ( ! vha - > flags . online ) {
ql_log ( ql_log_warn , vha , 0x70a1 , " Host is not online \n " ) ;
rval = - EIO ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
}
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:26:00 -07:00
ql_log ( ql_log_warn , vha , 0x70a1 , " App not started \n " ) ;
rval = - EIO ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
}
2022-01-09 21:02:13 -08:00
/* silent unaligned access warning */
portid . b . domain = sa_frame . port_id . b . domain ;
portid . b . area = sa_frame . port_id . b . area ;
portid . b . al_pa = sa_frame . port_id . b . al_pa ;
fcport = qla2x00_find_fcport_by_pid ( vha , & portid ) ;
2021-06-23 22:26:00 -07:00
if ( fcport ) {
found = 1 ;
if ( sa_frame . flags = = QLA_SA_UPDATE_FLAGS_TX_KEY )
fcport - > edif . tx_bytes = 0 ;
if ( sa_frame . flags = = QLA_SA_UPDATE_FLAGS_RX_KEY )
fcport - > edif . rx_bytes = 0 ;
}
if ( ! found ) {
ql_dbg ( ql_dbg_edif , vha , 0x70a3 , " Failed to find port= %06x \n " ,
sa_frame . port_id . b24 ) ;
rval = - EINVAL ;
2022-08-11 20:00:23 -05:00
SET_DID_STATUS ( bsg_reply - > result , DID_NO_CONNECT ) ;
2021-06-23 22:26:00 -07:00
goto done ;
}
/* make sure the nport_handle is valid */
if ( fcport - > loop_id = = FC_NO_LOOP_ID ) {
ql_dbg ( ql_dbg_edif , vha , 0x70e1 ,
" %s: %8phN lid=FC_NO_LOOP_ID, spi: 0x%x, DS %d, returning NO_CONNECT \n " ,
__func__ , fcport - > port_name , sa_frame . spi ,
fcport - > disc_state ) ;
rval = - EINVAL ;
SET_DID_STATUS ( bsg_reply - > result , DID_NO_CONNECT ) ;
goto done ;
}
/* allocate and queue an sa_ctl */
result = qla24xx_check_sadb_avail_slot ( bsg_job , fcport , & sa_frame ) ;
/* failure of bsg */
if ( result = = INVALID_EDIF_SA_INDEX ) {
ql_dbg ( ql_dbg_edif , vha , 0x70e1 ,
" %s: %8phN, skipping update. \n " ,
__func__ , fcport - > port_name ) ;
rval = - EINVAL ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
/* rx delete failure */
} else if ( result = = RX_DELETE_NO_EDIF_SA_INDEX ) {
ql_dbg ( ql_dbg_edif , vha , 0x70e1 ,
" %s: %8phN, skipping rx delete. \n " ,
__func__ , fcport - > port_name ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
goto done ;
}
ql_dbg ( ql_dbg_edif , vha , 0x70e1 ,
" %s: %8phN, sa_index in sa_frame: %d flags %xh \n " ,
__func__ , fcport - > port_name , sa_frame . fast_sa_index ,
sa_frame . flags ) ;
/* looking for rx index and delete */
if ( ( ( sa_frame . flags & SAU_FLG_TX ) = = 0 ) & &
( sa_frame . flags & SAU_FLG_INV ) ) {
uint16_t nport_handle = fcport - > loop_id ;
uint16_t sa_index = sa_frame . fast_sa_index ;
/*
* make sure we have an existing rx key , otherwise just process
* this as a straight delete just like TX
* This is NOT a normal case , it indicates an error recovery or key cleanup
* by the ipsec code above us .
*/
edif_entry = qla_edif_list_find_sa_index ( fcport , fcport - > loop_id ) ;
if ( ! edif_entry ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: WARNING: no active sa_index for nport_handle 0x%x, forcing delete for sa_index 0x%x \n " ,
__func__ , fcport - > loop_id , sa_index ) ;
goto force_rx_delete ;
}
/*
* if we have a forced delete for rx , remove the sa_index from the edif list
* and proceed with normal delete . The rx delay timer should not be running
*/
if ( ( sa_frame . flags & SAU_FLG_FORCE_DELETE ) = = SAU_FLG_FORCE_DELETE ) {
qla_edif_list_delete_sa_index ( fcport , edif_entry ) ;
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: FORCE DELETE flag found for nport_handle 0x%x, sa_index 0x%x, forcing DELETE \n " ,
__func__ , fcport - > loop_id , sa_index ) ;
kfree ( edif_entry ) ;
goto force_rx_delete ;
}
/*
* delayed rx delete
*
* if delete_sa_index is not invalid then there is already
* a delayed index in progress , return bsg bad status
*/
if ( edif_entry - > delete_sa_index ! = INVALID_EDIF_SA_INDEX ) {
struct edif_sa_ctl * sa_ctl ;
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: delete for lid 0x%x, delete_sa_index %d is pending \n " ,
__func__ , edif_entry - > handle , edif_entry - > delete_sa_index ) ;
/* free up the sa_ctl that was allocated with the sa_index */
sa_ctl = qla_edif_find_sa_ctl_by_index ( fcport , sa_index ,
( sa_frame . flags & SAU_FLG_TX ) ) ;
if ( sa_ctl ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_ctl for index %d \n " ,
__func__ , sa_ctl - > index ) ;
qla_edif_free_sa_ctl ( fcport , sa_ctl , sa_ctl - > index ) ;
}
/* release the sa_index */
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_index %d, nph: 0x%x \n " ,
__func__ , sa_index , nport_handle ) ;
qla_edif_sadb_delete_sa_index ( fcport , nport_handle , sa_index ) ;
rval = - EINVAL ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
goto done ;
}
fcport - > edif . rekey_cnt + + ;
/* configure and start the rx delay timer */
edif_entry - > fcport = fcport ;
edif_entry - > timer . expires = jiffies + RX_DELAY_DELETE_TIMEOUT * HZ ;
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: adding timer, entry: %p, delete sa_index %d, lid 0x%x to edif_list \n " ,
__func__ , edif_entry , sa_index , nport_handle ) ;
/*
* Start the timer when we queue the delayed rx delete .
* This is an activity timer that goes off if we have not
* received packets with the new sa_index
*/
add_timer ( & edif_entry - > timer ) ;
/*
* sa_delete for rx key with an active rx key including this one
* add the delete rx sa index to the hash so we can look for it
* in the rsp queue . Do this after making any changes to the
* edif_entry as part of the rx delete .
*/
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: delete sa_index %d, lid 0x%x to edif_list. bsg done ptr %p \n " ,
__func__ , sa_index , nport_handle , bsg_job ) ;
edif_entry - > delete_sa_index = sa_index ;
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
bsg_reply - > result = DID_OK < < 16 ;
goto done ;
/*
* rx index and update
* add the index to the list and continue with normal update
*/
} else if ( ( ( sa_frame . flags & SAU_FLG_TX ) = = 0 ) & &
( ( sa_frame . flags & SAU_FLG_INV ) = = 0 ) ) {
/* sa_update for rx key */
uint32_t nport_handle = fcport - > loop_id ;
uint16_t sa_index = sa_frame . fast_sa_index ;
int result ;
/*
* add the update rx sa index to the hash so we can look for it
* in the rsp queue and continue normally
*/
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: adding update sa_index %d, lid 0x%x to edif_list \n " ,
__func__ , sa_index , nport_handle ) ;
result = qla_edif_list_add_sa_update_index ( fcport , sa_index ,
nport_handle ) ;
if ( result ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: SA_UPDATE failed to add new sa index %d to list for lid 0x%x \n " ,
__func__ , sa_index , nport_handle ) ;
}
}
if ( sa_frame . flags & SAU_FLG_GMAC_MODE )
fcport - > edif . aes_gmac = 1 ;
else
fcport - > edif . aes_gmac = 0 ;
force_rx_delete :
/*
* sa_update for both rx and tx keys , sa_delete for tx key
* immediately process the request
*/
sp = qla2x00_get_sp ( vha , fcport , GFP_KERNEL ) ;
if ( ! sp ) {
rval = - ENOMEM ;
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
goto done ;
}
sp - > type = SRB_SA_UPDATE ;
sp - > name = " bsg_sa_update " ;
sp - > u . bsg_job = bsg_job ;
/* sp->free = qla2x00_bsg_sp_free; */
sp - > free = qla2x00_rel_sp ;
sp - > done = qla2x00_bsg_job_done ;
iocb_cmd = & sp - > u . iocb_cmd ;
iocb_cmd - > u . sa_update . sa_frame = sa_frame ;
2022-06-06 21:46:23 -07:00
cnt = 0 ;
retry :
2021-06-23 22:26:00 -07:00
rval = qla2x00_start_sp ( sp ) ;
2022-06-06 21:46:23 -07:00
switch ( rval ) {
case QLA_SUCCESS :
break ;
case EAGAIN :
msleep ( EDIF_MSLEEP_INTERVAL ) ;
cnt + + ;
if ( cnt < EDIF_RETRY_COUNT )
goto retry ;
fallthrough ;
default :
2021-06-23 22:26:00 -07:00
ql_log ( ql_dbg_edif , vha , 0x70e3 ,
2022-06-06 21:46:23 -07:00
" %s qla2x00_start_sp failed=%d. \n " ,
__func__ , rval ) ;
2021-06-23 22:26:00 -07:00
qla2x00_rel_sp ( sp ) ;
rval = - EIO ;
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
goto done ;
}
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: %s sent, hdl=%x, portid=%06x. \n " ,
__func__ , sp - > name , sp - > handle , fcport - > d_id . b24 ) ;
fcport - > edif . rekey_cnt + + ;
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_OK ) ;
return 0 ;
/*
* send back error status
*/
done :
bsg_job - > reply_len = sizeof ( struct fc_bsg_reply ) ;
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s:status: FAIL, result: 0x%x, bsg ptr done %p \n " ,
__func__ , bsg_reply - > result , bsg_job ) ;
bsg_job_done ( bsg_job , bsg_reply - > result ,
bsg_reply - > reply_payload_rcv_len ) ;
return 0 ;
}
2021-06-23 22:25:58 -07:00
static void
qla_enode_free ( scsi_qla_host_t * vha , struct enode * node )
{
node - > ntype = N_UNDEF ;
kfree ( node ) ;
}
/**
* qla_enode_init - initialize enode structs & lock
* @ vha : host adapter pointer
*
* should only be called when driver attaching
*/
void
qla_enode_init ( scsi_qla_host_t * vha )
{
struct qla_hw_data * ha = vha - > hw ;
char name [ 32 ] ;
if ( vha - > pur_cinfo . enode_flags = = ENODE_ACTIVE ) {
/* list still active - error */
ql_dbg ( ql_dbg_edif , vha , 0x09102 , " %s enode still active \n " ,
__func__ ) ;
return ;
}
/* initialize lock which protects pur_core & init list */
spin_lock_init ( & vha - > pur_cinfo . pur_lock ) ;
INIT_LIST_HEAD ( & vha - > pur_cinfo . head ) ;
snprintf ( name , sizeof ( name ) , " %s_%d_purex " , QLA2XXX_DRIVER_NAME ,
ha - > pdev - > device ) ;
}
/**
* qla_enode_stop - stop and clear and enode data
* @ vha : host adapter pointer
*
* called when app notified it is exiting
*/
2021-06-23 22:25:56 -07:00
void
qla_enode_stop ( scsi_qla_host_t * vha )
{
2021-06-23 22:25:58 -07:00
unsigned long flags ;
struct enode * node , * q ;
2021-06-23 22:25:56 -07:00
if ( vha - > pur_cinfo . enode_flags ! = ENODE_ACTIVE ) {
/* doorbell list not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s enode not active \n " , __func__ ) ;
return ;
}
2021-06-23 22:25:58 -07:00
/* grab lock so list doesn't move */
spin_lock_irqsave ( & vha - > pur_cinfo . pur_lock , flags ) ;
vha - > pur_cinfo . enode_flags & = ~ ENODE_ACTIVE ; /* mark it not active */
/* hopefully this is a null list at this point */
list_for_each_entry_safe ( node , q , & vha - > pur_cinfo . head , list ) {
ql_dbg ( ql_dbg_edif , vha , 0x910f ,
" %s freeing enode type=%x, cnt=%x \n " , __func__ , node - > ntype ,
node - > dinfo . nodecnt ) ;
list_del_init ( & node - > list ) ;
qla_enode_free ( vha , node ) ;
}
spin_unlock_irqrestore ( & vha - > pur_cinfo . pur_lock , flags ) ;
}
2021-10-26 04:54:05 -07:00
static void qla_enode_clear ( scsi_qla_host_t * vha , port_id_t portid )
{
unsigned long flags ;
struct enode * e , * tmp ;
struct purexevent * purex ;
LIST_HEAD ( enode_list ) ;
if ( vha - > pur_cinfo . enode_flags ! = ENODE_ACTIVE ) {
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s enode not active \n " , __func__ ) ;
return ;
}
spin_lock_irqsave ( & vha - > pur_cinfo . pur_lock , flags ) ;
list_for_each_entry_safe ( e , tmp , & vha - > pur_cinfo . head , list ) {
purex = & e - > u . purexinfo ;
if ( purex - > pur_info . pur_sid . b24 = = portid . b24 ) {
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s free ELS sid=%06x. xchg %x, nb=%xh \n " ,
__func__ , portid . b24 ,
purex - > pur_info . pur_rx_xchg_address ,
purex - > pur_info . pur_bytes_rcvd ) ;
list_del_init ( & e - > list ) ;
list_add_tail ( & e - > list , & enode_list ) ;
}
}
spin_unlock_irqrestore ( & vha - > pur_cinfo . pur_lock , flags ) ;
list_for_each_entry_safe ( e , tmp , & enode_list , list ) {
list_del_init ( & e - > list ) ;
qla_enode_free ( vha , e ) ;
}
}
2021-06-23 22:25:59 -07:00
/*
* allocate enode struct and populate buffer
* returns : enode pointer with buffers
* NULL on error
*/
static struct enode *
qla_enode_alloc ( scsi_qla_host_t * vha , uint32_t ntype )
{
struct enode * node ;
struct purexevent * purex ;
node = kzalloc ( RX_ELS_SIZE , GFP_ATOMIC ) ;
if ( ! node )
return NULL ;
purex = & node - > u . purexinfo ;
purex - > msgp = ( u8 * ) ( node + 1 ) ;
purex - > msgp_len = ELS_MAX_PAYLOAD ;
node - > ntype = ntype ;
INIT_LIST_HEAD ( & node - > list ) ;
return node ;
}
static void
qla_enode_add ( scsi_qla_host_t * vha , struct enode * ptr )
{
unsigned long flags ;
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x9109 ,
" %s add enode for type=%x, cnt=%x \n " ,
__func__ , ptr - > ntype , ptr - > dinfo . nodecnt ) ;
spin_lock_irqsave ( & vha - > pur_cinfo . pur_lock , flags ) ;
list_add_tail ( & ptr - > list , & vha - > pur_cinfo . head ) ;
spin_unlock_irqrestore ( & vha - > pur_cinfo . pur_lock , flags ) ;
return ;
}
2021-06-23 22:25:58 -07:00
static struct enode *
qla_enode_find ( scsi_qla_host_t * vha , uint32_t ntype , uint32_t p1 , uint32_t p2 )
{
struct enode * node_rtn = NULL ;
2021-10-26 04:54:06 -07:00
struct enode * list_node , * q ;
2021-06-23 22:25:58 -07:00
unsigned long flags ;
uint32_t sid ;
struct purexevent * purex ;
/* secure the list from moving under us */
spin_lock_irqsave ( & vha - > pur_cinfo . pur_lock , flags ) ;
2021-10-26 04:54:06 -07:00
list_for_each_entry_safe ( list_node , q , & vha - > pur_cinfo . head , list ) {
2021-06-23 22:25:58 -07:00
/* node type determines what p1 and p2 are */
purex = & list_node - > u . purexinfo ;
sid = p1 ;
if ( purex - > pur_info . pur_sid . b24 = = sid ) {
2021-10-26 04:54:06 -07:00
/* found it and its complete */
node_rtn = list_node ;
list_del ( & list_node - > list ) ;
break ;
2021-06-23 22:25:58 -07:00
}
}
spin_unlock_irqrestore ( & vha - > pur_cinfo . pur_lock , flags ) ;
return node_rtn ;
2021-06-23 22:25:56 -07:00
}
2021-06-23 22:25:58 -07:00
/**
* qla_pur_get_pending - read / return authentication message sent
* from remote port
* @ vha : host adapter pointer
* @ fcport : session pointer
* @ bsg_job : user request where the message is copy to .
*/
static int
qla_pur_get_pending ( scsi_qla_host_t * vha , fc_port_t * fcport ,
struct bsg_job * bsg_job )
{
struct enode * ptr ;
struct purexevent * purex ;
struct qla_bsg_auth_els_reply * rpl =
( struct qla_bsg_auth_els_reply * ) bsg_job - > reply ;
bsg_job - > reply_len = sizeof ( * rpl ) ;
ptr = qla_enode_find ( vha , N_PUREX , fcport - > d_id . b24 , PUR_GET ) ;
if ( ! ptr ) {
ql_dbg ( ql_dbg_edif , vha , 0x9111 ,
" %s no enode data found for %8phN sid=%06x \n " ,
__func__ , fcport - > port_name , fcport - > d_id . b24 ) ;
SET_DID_STATUS ( rpl - > r . result , DID_IMM_RETRY ) ;
return - EIO ;
}
/*
* enode is now off the linked list and is ours to deal with
*/
purex = & ptr - > u . purexinfo ;
/* Copy info back to caller */
rpl - > rx_xchg_address = purex - > pur_info . pur_rx_xchg_address ;
SET_DID_STATUS ( rpl - > r . result , DID_OK ) ;
rpl - > r . reply_payload_rcv_len =
sg_pcopy_from_buffer ( bsg_job - > reply_payload . sg_list ,
bsg_job - > reply_payload . sg_cnt , purex - > msgp ,
purex - > pur_info . pur_bytes_rcvd , 0 ) ;
/* data copy / passback completed - destroy enode */
qla_enode_free ( vha , ptr ) ;
return 0 ;
}
2021-06-23 22:25:59 -07:00
/* it is assume qpair lock is held */
static int
qla_els_reject_iocb ( scsi_qla_host_t * vha , struct qla_qpair * qp ,
struct qla_els_pt_arg * a )
{
struct els_entry_24xx * els_iocb ;
els_iocb = __qla2x00_alloc_iocbs ( qp , NULL ) ;
if ( ! els_iocb ) {
ql_log ( ql_log_warn , vha , 0x700c ,
" qla2x00_alloc_iocbs failed. \n " ) ;
return QLA_FUNCTION_FAILED ;
}
qla_els_pt_iocb ( vha , els_iocb , a ) ;
ql_dbg ( ql_dbg_edif , vha , 0x0183 ,
2021-10-26 04:54:07 -07:00
" Sending ELS reject ox_id %04x s:%06x -> d:%06x \n " ,
a - > ox_id , a - > sid . b24 , a - > did . b24 ) ;
2021-06-23 22:25:59 -07:00
ql_dump_buffer ( ql_dbg_edif + ql_dbg_verbose , vha , 0x0185 ,
vha - > hw - > elsrej . c , sizeof ( * vha - > hw - > elsrej . c ) ) ;
/* flush iocb to mem before notifying hw doorbell */
wmb ( ) ;
qla2x00_start_iocbs ( vha , qp - > req ) ;
return 0 ;
}
2021-06-23 22:26:03 -07:00
void
qla_edb_init ( scsi_qla_host_t * vha )
{
2021-10-26 04:54:10 -07:00
if ( DBELL_ACTIVE ( vha ) ) {
2021-06-23 22:26:03 -07:00
/* list already init'd - error */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" edif db already initialized, cannot reinit \n " ) ;
return ;
}
/* initialize lock which protects doorbell & init list */
spin_lock_init ( & vha - > e_dbell . db_lock ) ;
INIT_LIST_HEAD ( & vha - > e_dbell . head ) ;
}
2021-10-26 04:54:05 -07:00
static void qla_edb_clear ( scsi_qla_host_t * vha , port_id_t portid )
{
unsigned long flags ;
struct edb_node * e , * tmp ;
port_id_t sid ;
LIST_HEAD ( edb_list ) ;
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-10-26 04:54:05 -07:00
/* doorbell list not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s doorbell not enabled \n " , __func__ ) ;
return ;
}
/* grab lock so list doesn't move */
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
list_for_each_entry_safe ( e , tmp , & vha - > e_dbell . head , list ) {
switch ( e - > ntype ) {
case VND_CMD_AUTH_STATE_NEEDED :
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN :
sid = e - > u . plogi_did ;
break ;
case VND_CMD_AUTH_STATE_ELS_RCVD :
sid = e - > u . els_sid ;
break ;
case VND_CMD_AUTH_STATE_SAUPDATE_COMPL :
/* app wants to see this */
continue ;
default :
ql_log ( ql_log_warn , vha , 0x09102 ,
" %s unknown node type: %x \n " , __func__ , e - > ntype ) ;
sid . b24 = 0 ;
break ;
}
if ( sid . b24 = = portid . b24 ) {
ql_dbg ( ql_dbg_edif , vha , 0x910f ,
" %s free doorbell event : node type = %x %p \n " ,
__func__ , e - > ntype , e ) ;
list_del_init ( & e - > list ) ;
list_add_tail ( & e - > list , & edb_list ) ;
}
}
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
2022-06-06 21:46:20 -07:00
list_for_each_entry_safe ( e , tmp , & edb_list , list )
2021-10-26 04:54:05 -07:00
qla_edb_node_free ( vha , e ) ;
}
2021-06-23 22:25:56 -07:00
/* function called when app is stopping */
void
qla_edb_stop ( scsi_qla_host_t * vha )
{
2021-06-23 22:26:03 -07:00
unsigned long flags ;
struct edb_node * node , * q ;
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:26:03 -07:00
/* doorbell list not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s doorbell not enabled \n " , __func__ ) ;
return ;
}
/* grab lock so list doesn't move */
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
vha - > e_dbell . db_flags & = ~ EDB_ACTIVE ; /* mark it not active */
/* hopefully this is a null list at this point */
list_for_each_entry_safe ( node , q , & vha - > e_dbell . head , list ) {
ql_dbg ( ql_dbg_edif , vha , 0x910f ,
" %s freeing edb_node type=%x \n " ,
__func__ , node - > ntype ) ;
qla_edb_node_free ( vha , node ) ;
}
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
2022-06-06 21:46:20 -07:00
qla_edif_dbell_bsg_done ( vha ) ;
2021-06-23 22:26:03 -07:00
}
static struct edb_node *
qla_edb_node_alloc ( scsi_qla_host_t * vha , uint32_t ntype )
{
struct edb_node * node ;
node = kzalloc ( sizeof ( * node ) , GFP_ATOMIC ) ;
if ( ! node ) {
/* couldn't get space */
ql_dbg ( ql_dbg_edif , vha , 0x9100 ,
" edb node unable to be allocated \n " ) ;
return NULL ;
}
node - > ntype = ntype ;
INIT_LIST_HEAD ( & node - > list ) ;
return node ;
}
2021-07-29 09:24:13 +01:00
/* adds a already allocated enode to the linked list */
2021-06-23 22:26:03 -07:00
static bool
qla_edb_node_add ( scsi_qla_host_t * vha , struct edb_node * ptr )
{
unsigned long flags ;
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:25:56 -07:00
/* doorbell list not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s doorbell not enabled \n " , __func__ ) ;
2021-06-23 22:26:03 -07:00
return false ;
}
spin_lock_irqsave ( & vha - > e_dbell . db_lock , flags ) ;
list_add_tail ( & ptr - > list , & vha - > e_dbell . head ) ;
spin_unlock_irqrestore ( & vha - > e_dbell . db_lock , flags ) ;
return true ;
}
/* adds event to doorbell list */
void
qla_edb_eventcreate ( scsi_qla_host_t * vha , uint32_t dbtype ,
uint32_t data , uint32_t data2 , fc_port_t * sfcport )
{
struct edb_node * edbnode ;
fc_port_t * fcport = sfcport ;
port_id_t id ;
if ( ! vha - > hw - > flags . edif_enabled ) {
/* edif not enabled */
2021-06-23 22:25:56 -07:00
return ;
}
2021-06-23 22:26:03 -07:00
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:26:03 -07:00
if ( fcport )
fcport - > edif . auth_state = dbtype ;
/* doorbell list not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s doorbell not enabled (type=%d \n " , __func__ , dbtype ) ;
return ;
}
edbnode = qla_edb_node_alloc ( vha , dbtype ) ;
if ( ! edbnode ) {
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s unable to alloc db node \n " , __func__ ) ;
return ;
}
if ( ! fcport ) {
id . b . domain = ( data > > 16 ) & 0xff ;
id . b . area = ( data > > 8 ) & 0xff ;
id . b . al_pa = data & 0xff ;
ql_dbg ( ql_dbg_edif , vha , 0x09222 ,
" %s: Arrived s_id: %06x \n " , __func__ ,
id . b24 ) ;
fcport = qla2x00_find_fcport_by_pid ( vha , & id ) ;
if ( ! fcport ) {
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s can't find fcport for sid= 0x%x - ignoring \n " ,
__func__ , id . b24 ) ;
kfree ( edbnode ) ;
return ;
}
}
/* populate the edb node */
switch ( dbtype ) {
case VND_CMD_AUTH_STATE_NEEDED :
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN :
edbnode - > u . plogi_did . b24 = fcport - > d_id . b24 ;
break ;
case VND_CMD_AUTH_STATE_ELS_RCVD :
edbnode - > u . els_sid . b24 = fcport - > d_id . b24 ;
break ;
case VND_CMD_AUTH_STATE_SAUPDATE_COMPL :
edbnode - > u . sa_aen . port_id = fcport - > d_id ;
edbnode - > u . sa_aen . status = data ;
edbnode - > u . sa_aen . key_type = data2 ;
2022-06-06 21:46:18 -07:00
edbnode - > u . sa_aen . version = EDIF_VERSION1 ;
2021-06-23 22:26:03 -07:00
break ;
default :
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s unknown type: %x \n " , __func__ , dbtype ) ;
kfree ( edbnode ) ;
edbnode = NULL ;
break ;
}
2022-06-06 21:46:20 -07:00
if ( edbnode ) {
if ( ! qla_edb_node_add ( vha , edbnode ) ) {
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
" %s unable to add dbnode \n " , __func__ ) ;
kfree ( edbnode ) ;
return ;
}
2021-06-23 22:26:03 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x09102 ,
2022-06-06 21:46:20 -07:00
" %s Doorbell produced : type=%d %p \n " , __func__ , dbtype , edbnode ) ;
qla_edif_dbell_bsg_done ( vha ) ;
if ( fcport )
fcport - > edif . auth_state = dbtype ;
2021-06-23 22:26:03 -07:00
}
}
2021-08-16 22:13:08 -07:00
void
qla_edif_timer ( scsi_qla_host_t * vha )
{
struct qla_hw_data * ha = vha - > hw ;
if ( ! vha - > vp_idx & & N2N_TOPO ( ha ) & & ha - > flags . n2n_fw_acc_sec ) {
2021-10-26 04:54:10 -07:00
if ( DBELL_INACTIVE ( vha ) & &
2021-08-16 22:13:08 -07:00
ha - > edif_post_stop_cnt_down ) {
ha - > edif_post_stop_cnt_down - - ;
/*
* turn off auto ' Plogi Acc + secure = 1 ' feature
* Set Add FW option [ 3 ]
* BIT_15 , if .
*/
if ( ha - > edif_post_stop_cnt_down = = 0 ) {
ql_dbg ( ql_dbg_async , vha , 0x911d ,
" %s chip reset to turn off PLOGI ACC + secure \n " ,
__func__ ) ;
set_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) ;
}
} else {
ha - > edif_post_stop_cnt_down = 60 ;
}
}
2022-06-06 21:46:20 -07:00
if ( vha - > e_dbell . dbell_bsg_job & & time_after_eq ( jiffies , vha - > e_dbell . bsg_expire ) )
qla_edif_dbell_bsg_done ( vha ) ;
2021-08-16 22:13:08 -07:00
}
2021-06-23 22:26:00 -07:00
static void qla_noop_sp_done ( srb_t * sp , int res )
{
2022-06-06 21:46:21 -07:00
sp - > fcport - > flags & = ~ ( FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE ) ;
2022-01-09 21:02:03 -08:00
/* ref: INIT */
kref_put ( & sp - > cmd_kref , qla2x00_sp_release ) ;
2021-06-23 22:26:00 -07:00
}
/*
* Called from work queue
* build and send the sa_update iocb to delete an rx sa_index
*/
int
qla24xx_issue_sa_replace_iocb ( scsi_qla_host_t * vha , struct qla_work_evt * e )
{
srb_t * sp ;
fc_port_t * fcport = NULL ;
struct srb_iocb * iocb_cmd = NULL ;
int rval = QLA_SUCCESS ;
struct edif_sa_ctl * sa_ctl = e - > u . sa_update . sa_ctl ;
uint16_t nport_handle = e - > u . sa_update . nport_handle ;
ql_dbg ( ql_dbg_edif , vha , 0x70e6 ,
" %s: starting, sa_ctl: %p \n " , __func__ , sa_ctl ) ;
if ( ! sa_ctl ) {
ql_dbg ( ql_dbg_edif , vha , 0x70e6 ,
" sa_ctl allocation failed \n " ) ;
2022-06-06 21:46:21 -07:00
rval = - ENOMEM ;
goto done ;
2021-06-23 22:26:00 -07:00
}
fcport = sa_ctl - > fcport ;
/* Alloc SRB structure */
sp = qla2x00_get_sp ( vha , fcport , GFP_KERNEL ) ;
if ( ! sp ) {
ql_dbg ( ql_dbg_edif , vha , 0x70e6 ,
" SRB allocation failed \n " ) ;
2022-06-06 21:46:21 -07:00
rval = - ENOMEM ;
goto done ;
2021-06-23 22:26:00 -07:00
}
fcport - > flags | = FCF_ASYNC_SENT ;
iocb_cmd = & sp - > u . iocb_cmd ;
iocb_cmd - > u . sa_update . sa_ctl = sa_ctl ;
ql_dbg ( ql_dbg_edif , vha , 0x3073 ,
" Enter: SA REPL portid=%06x, sa_ctl %p, index %x, nport_handle: 0x%x \n " ,
fcport - > d_id . b24 , sa_ctl , sa_ctl - > index , nport_handle ) ;
/*
* if this is a sadb cleanup delete , mark it so the isr can
* take the correct action
*/
if ( sa_ctl - > flags & EDIF_SA_CTL_FLG_CLEANUP_DEL ) {
/* mark this srb as a cleanup delete */
sp - > flags | = SRB_EDIF_CLEANUP_DELETE ;
ql_dbg ( ql_dbg_edif , vha , 0x70e6 ,
" %s: sp 0x%p flagged as cleanup delete \n " , __func__ , sp ) ;
}
sp - > type = SRB_SA_REPLACE ;
sp - > name = " SA_REPLACE " ;
sp - > fcport = fcport ;
sp - > free = qla2x00_rel_sp ;
sp - > done = qla_noop_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2022-06-06 21:46:21 -07:00
if ( rval ! = QLA_SUCCESS ) {
goto done_free_sp ;
}
2021-06-23 22:26:00 -07:00
2022-06-06 21:46:21 -07:00
return rval ;
done_free_sp :
kref_put ( & sp - > cmd_kref , qla2x00_sp_release ) ;
fcport - > flags & = ~ FCF_ASYNC_SENT ;
done :
fcport - > flags & = ~ FCF_ASYNC_ACTIVE ;
2021-06-23 22:26:00 -07:00
return rval ;
}
void qla24xx_sa_update_iocb ( srb_t * sp , struct sa_update_28xx * sa_update_iocb )
{
int itr = 0 ;
struct scsi_qla_host * vha = sp - > vha ;
struct qla_sa_update_frame * sa_frame =
& sp - > u . iocb_cmd . u . sa_update . sa_frame ;
u8 flags = 0 ;
switch ( sa_frame - > flags & ( SAU_FLG_INV | SAU_FLG_TX ) ) {
case 0 :
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , sa_frame - > fast_sa_index ) ;
break ;
case 1 :
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , sa_frame - > fast_sa_index ) ;
flags | = SA_FLAG_INVALIDATE ;
break ;
case 2 :
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , sa_frame - > fast_sa_index ) ;
flags | = SA_FLAG_TX ;
break ;
case 3 :
ql_dbg ( ql_dbg_edif , vha , 0x911d ,
" %s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , sa_frame - > fast_sa_index ) ;
flags | = SA_FLAG_TX | SA_FLAG_INVALIDATE ;
break ;
}
sa_update_iocb - > entry_type = SA_UPDATE_IOCB_TYPE ;
sa_update_iocb - > entry_count = 1 ;
sa_update_iocb - > sys_define = 0 ;
sa_update_iocb - > entry_status = 0 ;
sa_update_iocb - > handle = sp - > handle ;
sa_update_iocb - > u . nport_handle = cpu_to_le16 ( sp - > fcport - > loop_id ) ;
sa_update_iocb - > vp_index = sp - > fcport - > vha - > vp_idx ;
sa_update_iocb - > port_id [ 0 ] = sp - > fcport - > d_id . b . al_pa ;
sa_update_iocb - > port_id [ 1 ] = sp - > fcport - > d_id . b . area ;
sa_update_iocb - > port_id [ 2 ] = sp - > fcport - > d_id . b . domain ;
sa_update_iocb - > flags = flags ;
sa_update_iocb - > salt = cpu_to_le32 ( sa_frame - > salt ) ;
sa_update_iocb - > spi = cpu_to_le32 ( sa_frame - > spi ) ;
sa_update_iocb - > sa_index = cpu_to_le16 ( sa_frame - > fast_sa_index ) ;
sa_update_iocb - > sa_control | = SA_CNTL_ENC_FCSP ;
if ( sp - > fcport - > edif . aes_gmac )
sa_update_iocb - > sa_control | = SA_CNTL_AES_GMAC ;
if ( sa_frame - > flags & SAU_FLG_KEY256 ) {
sa_update_iocb - > sa_control | = SA_CNTL_KEY256 ;
for ( itr = 0 ; itr < 32 ; itr + + )
sa_update_iocb - > sa_key [ itr ] = sa_frame - > sa_key [ itr ] ;
} else {
sa_update_iocb - > sa_control | = SA_CNTL_KEY128 ;
for ( itr = 0 ; itr < 16 ; itr + + )
sa_update_iocb - > sa_key [ itr ] = sa_frame - > sa_key [ itr ] ;
}
ql_dbg ( ql_dbg_edif , vha , 0x921d ,
" %s SAU Port ID = %02x%02x%02x, flags=%xh, index=%u, ctl=%xh, SPI 0x%x flags 0x%x hdl=%x gmac %d \n " ,
__func__ , sa_update_iocb - > port_id [ 2 ] , sa_update_iocb - > port_id [ 1 ] ,
sa_update_iocb - > port_id [ 0 ] , sa_update_iocb - > flags , sa_update_iocb - > sa_index ,
sa_update_iocb - > sa_control , sa_update_iocb - > spi , sa_frame - > flags , sp - > handle ,
sp - > fcport - > edif . aes_gmac ) ;
if ( sa_frame - > flags & SAU_FLG_TX )
sp - > fcport - > edif . tx_sa_pending = 1 ;
else
sp - > fcport - > edif . rx_sa_pending = 1 ;
sp - > fcport - > vha - > qla_stats . control_requests + + ;
}
void
qla24xx_sa_replace_iocb ( srb_t * sp , struct sa_update_28xx * sa_update_iocb )
{
struct scsi_qla_host * vha = sp - > vha ;
struct srb_iocb * srb_iocb = & sp - > u . iocb_cmd ;
struct edif_sa_ctl * sa_ctl = srb_iocb - > u . sa_update . sa_ctl ;
uint16_t nport_handle = sp - > fcport - > loop_id ;
sa_update_iocb - > entry_type = SA_UPDATE_IOCB_TYPE ;
sa_update_iocb - > entry_count = 1 ;
sa_update_iocb - > sys_define = 0 ;
sa_update_iocb - > entry_status = 0 ;
sa_update_iocb - > handle = sp - > handle ;
sa_update_iocb - > u . nport_handle = cpu_to_le16 ( nport_handle ) ;
sa_update_iocb - > vp_index = sp - > fcport - > vha - > vp_idx ;
sa_update_iocb - > port_id [ 0 ] = sp - > fcport - > d_id . b . al_pa ;
sa_update_iocb - > port_id [ 1 ] = sp - > fcport - > d_id . b . area ;
sa_update_iocb - > port_id [ 2 ] = sp - > fcport - > d_id . b . domain ;
/* Invalidate the index. salt, spi, control & key are ignore */
sa_update_iocb - > flags = SA_FLAG_INVALIDATE ;
sa_update_iocb - > salt = 0 ;
sa_update_iocb - > spi = 0 ;
sa_update_iocb - > sa_index = cpu_to_le16 ( sa_ctl - > index ) ;
sa_update_iocb - > sa_control = 0 ;
ql_dbg ( ql_dbg_edif , vha , 0x921d ,
" %s SAU DELETE RX Port ID = %02x:%02x:%02x, lid %d flags=%xh, index=%u, hdl=%x \n " ,
__func__ , sa_update_iocb - > port_id [ 2 ] , sa_update_iocb - > port_id [ 1 ] ,
sa_update_iocb - > port_id [ 0 ] , nport_handle , sa_update_iocb - > flags ,
sa_update_iocb - > sa_index , sp - > handle ) ;
sp - > fcport - > vha - > qla_stats . control_requests + + ;
}
2021-06-23 22:25:59 -07:00
void qla24xx_auth_els ( scsi_qla_host_t * vha , void * * pkt , struct rsp_que * * rsp )
{
struct purex_entry_24xx * p = * pkt ;
struct enode * ptr ;
int sid ;
u16 totlen ;
struct purexevent * purex ;
struct scsi_qla_host * host = NULL ;
int rc ;
struct fc_port * fcport ;
struct qla_els_pt_arg a ;
be_id_t beid ;
memset ( & a , 0 , sizeof ( a ) ) ;
a . els_opcode = ELS_AUTH_ELS ;
a . nport_handle = p - > nport_handle ;
a . rx_xchg_address = p - > rx_xchg_addr ;
a . did . b . domain = p - > s_id [ 2 ] ;
a . did . b . area = p - > s_id [ 1 ] ;
a . did . b . al_pa = p - > s_id [ 0 ] ;
a . tx_byte_count = a . tx_len = sizeof ( struct fc_els_ls_rjt ) ;
a . tx_addr = vha - > hw - > elsrej . cdma ;
a . vp_idx = vha - > vp_idx ;
a . control_flags = EPD_ELS_RJT ;
2021-10-26 04:54:07 -07:00
a . ox_id = le16_to_cpu ( p - > ox_id ) ;
2021-06-23 22:25:59 -07:00
sid = p - > s_id [ 0 ] | ( p - > s_id [ 1 ] < < 8 ) | ( p - > s_id [ 2 ] < < 16 ) ;
totlen = ( le16_to_cpu ( p - > frame_size ) & 0x0fff ) - PURX_ELS_HEADER_SIZE ;
if ( le16_to_cpu ( p - > status_flags ) & 0x8000 ) {
totlen = le16_to_cpu ( p - > trunc_frame_size ) ;
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
__qla_consume_iocb ( vha , pkt , rsp ) ;
return ;
}
2021-10-26 04:54:09 -07:00
if ( totlen > ELS_MAX_PAYLOAD ) {
2021-06-23 22:25:59 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x0910d ,
" %s WARNING: verbose ELS frame received (totlen=%x) \n " ,
__func__ , totlen ) ;
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
__qla_consume_iocb ( vha , pkt , rsp ) ;
return ;
}
if ( ! vha - > hw - > flags . edif_enabled ) {
/* edif support not enabled */
ql_dbg ( ql_dbg_edif , vha , 0x910e , " %s edif not enabled \n " ,
__func__ ) ;
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
__qla_consume_iocb ( vha , pkt , rsp ) ;
return ;
}
ptr = qla_enode_alloc ( vha , N_PUREX ) ;
if ( ! ptr ) {
ql_dbg ( ql_dbg_edif , vha , 0x09109 ,
2021-07-29 09:24:13 +01:00
" WARNING: enode alloc failed for sid=%x \n " ,
2021-06-23 22:25:59 -07:00
sid ) ;
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
__qla_consume_iocb ( vha , pkt , rsp ) ;
return ;
}
purex = & ptr - > u . purexinfo ;
purex - > pur_info . pur_sid = a . did ;
purex - > pur_info . pur_bytes_rcvd = totlen ;
purex - > pur_info . pur_rx_xchg_address = le32_to_cpu ( p - > rx_xchg_addr ) ;
purex - > pur_info . pur_nphdl = le16_to_cpu ( p - > nport_handle ) ;
purex - > pur_info . pur_did . b . domain = p - > d_id [ 2 ] ;
purex - > pur_info . pur_did . b . area = p - > d_id [ 1 ] ;
purex - > pur_info . pur_did . b . al_pa = p - > d_id [ 0 ] ;
purex - > pur_info . vp_idx = p - > vp_idx ;
2021-10-26 04:54:07 -07:00
a . sid = purex - > pur_info . pur_did ;
2021-06-23 22:25:59 -07:00
rc = __qla_copy_purex_to_buffer ( vha , pkt , rsp , purex - > msgp ,
purex - > msgp_len ) ;
if ( rc ) {
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
qla_enode_free ( vha , ptr ) ;
return ;
}
beid . al_pa = purex - > pur_info . pur_did . b . al_pa ;
beid . area = purex - > pur_info . pur_did . b . area ;
beid . domain = purex - > pur_info . pur_did . b . domain ;
host = qla_find_host_by_d_id ( vha , beid ) ;
if ( ! host ) {
ql_log ( ql_log_fatal , vha , 0x508b ,
" %s Drop ELS due to unable to find host %06x \n " ,
__func__ , purex - > pur_info . pur_did . b24 ) ;
qla_els_reject_iocb ( vha , ( * rsp ) - > qpair , & a ) ;
qla_enode_free ( vha , ptr ) ;
return ;
}
fcport = qla2x00_find_fcport_by_pid ( host , & purex - > pur_info . pur_sid ) ;
2022-06-08 04:58:41 -07:00
if ( DBELL_INACTIVE ( vha ) ) {
2021-06-23 22:25:59 -07:00
ql_dbg ( ql_dbg_edif , host , 0x0910c , " %s e_dbell.db_flags =%x %06x \n " ,
__func__ , host - > e_dbell . db_flags ,
fcport ? fcport - > d_id . b24 : 0 ) ;
qla_els_reject_iocb ( host , ( * rsp ) - > qpair , & a ) ;
qla_enode_free ( host , ptr ) ;
return ;
}
2022-06-08 04:58:41 -07:00
if ( fcport & & EDIF_SESSION_DOWN ( fcport ) ) {
ql_dbg ( ql_dbg_edif , host , 0x13b6 ,
" %s terminate exchange. Send logo to 0x%x \n " ,
__func__ , a . did . b24 ) ;
a . tx_byte_count = a . tx_len = 0 ;
a . tx_addr = 0 ;
a . control_flags = EPD_RX_XCHG ; /* EPD_RX_XCHG = terminate cmd */
qla_els_reject_iocb ( host , ( * rsp ) - > qpair , & a ) ;
qla_enode_free ( host , ptr ) ;
/* send logo to let remote port knows to tear down session */
fcport - > send_els_logo = 1 ;
qlt_schedule_sess_for_deletion ( fcport ) ;
return ;
}
2021-06-23 22:25:59 -07:00
/* add the local enode to the list */
qla_enode_add ( host , ptr ) ;
ql_dbg ( ql_dbg_edif , host , 0x0910c ,
" %s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh \n " ,
__func__ , purex - > pur_info . pur_bytes_rcvd , purex - > pur_info . pur_sid . b24 ,
2021-10-26 04:54:05 -07:00
purex - > pur_info . pur_did . b24 , purex - > pur_info . pur_rx_xchg_address ) ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( host , VND_CMD_AUTH_STATE_ELS_RCVD , sid , 0 , NULL ) ;
2021-06-23 22:25:59 -07:00
}
2021-06-23 22:26:00 -07:00
static uint16_t qla_edif_get_sa_index_from_freepool ( fc_port_t * fcport , int dir )
{
struct scsi_qla_host * vha = fcport - > vha ;
struct qla_hw_data * ha = vha - > hw ;
void * sa_id_map ;
unsigned long flags = 0 ;
u16 sa_index ;
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x3063 ,
" %s: entry \n " , __func__ ) ;
if ( dir )
sa_id_map = ha - > edif_tx_sa_id_map ;
else
sa_id_map = ha - > edif_rx_sa_id_map ;
spin_lock_irqsave ( & ha - > sadb_fp_lock , flags ) ;
sa_index = find_first_zero_bit ( sa_id_map , EDIF_NUM_SA_INDEX ) ;
if ( sa_index > = EDIF_NUM_SA_INDEX ) {
spin_unlock_irqrestore ( & ha - > sadb_fp_lock , flags ) ;
return INVALID_EDIF_SA_INDEX ;
}
set_bit ( sa_index , sa_id_map ) ;
spin_unlock_irqrestore ( & ha - > sadb_fp_lock , flags ) ;
if ( dir )
sa_index + = EDIF_TX_SA_INDEX_BASE ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: index retrieved from free pool %d \n " , __func__ , sa_index ) ;
return sa_index ;
}
/* find an sadb entry for an nport_handle */
static struct edif_sa_index_entry *
qla_edif_sadb_find_sa_index_entry ( uint16_t nport_handle ,
struct list_head * sa_list )
{
struct edif_sa_index_entry * entry ;
struct edif_sa_index_entry * tentry ;
struct list_head * indx_list = sa_list ;
list_for_each_entry_safe ( entry , tentry , indx_list , next ) {
if ( entry - > handle = = nport_handle )
return entry ;
}
return NULL ;
}
/* remove an sa_index from the nport_handle and return it to the free pool */
static int qla_edif_sadb_delete_sa_index ( fc_port_t * fcport , uint16_t nport_handle ,
uint16_t sa_index )
{
struct edif_sa_index_entry * entry ;
struct list_head * sa_list ;
int dir = ( sa_index < EDIF_TX_SA_INDEX_BASE ) ? 0 : 1 ;
int slot = 0 ;
int free_slot_count = 0 ;
scsi_qla_host_t * vha = fcport - > vha ;
struct qla_hw_data * ha = vha - > hw ;
unsigned long flags = 0 ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: entry \n " , __func__ ) ;
if ( dir )
sa_list = & ha - > sadb_tx_index_list ;
else
sa_list = & ha - > sadb_rx_index_list ;
entry = qla_edif_sadb_find_sa_index_entry ( nport_handle , sa_list ) ;
if ( ! entry ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: no entry found for nport_handle 0x%x \n " ,
__func__ , nport_handle ) ;
return - 1 ;
}
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
/*
* each tx / rx direction has up to 2 sa indexes / slots . 1 slot for in flight traffic
* the other is use at re - key time .
*/
for ( slot = 0 ; slot < 2 ; slot + + ) {
if ( entry - > sa_pair [ slot ] . sa_index = = sa_index ) {
entry - > sa_pair [ slot ] . sa_index = INVALID_EDIF_SA_INDEX ;
entry - > sa_pair [ slot ] . spi = 0 ;
free_slot_count + + ;
qla_edif_add_sa_index_to_freepool ( fcport , dir , sa_index ) ;
} else if ( entry - > sa_pair [ slot ] . sa_index = = INVALID_EDIF_SA_INDEX ) {
free_slot_count + + ;
}
}
if ( free_slot_count = = 2 ) {
list_del ( & entry - > next ) ;
kfree ( entry ) ;
}
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sa_index %d removed, free_slot_count: %d \n " ,
__func__ , sa_index , free_slot_count ) ;
return 0 ;
}
void
qla28xx_sa_update_iocb_entry ( scsi_qla_host_t * v , struct req_que * req ,
struct sa_update_28xx * pkt )
{
const char * func = " SA_UPDATE_RESPONSE_IOCB " ;
srb_t * sp ;
struct edif_sa_ctl * sa_ctl ;
int old_sa_deleted = 1 ;
uint16_t nport_handle ;
struct scsi_qla_host * vha ;
sp = qla2x00_get_sp_from_handle ( v , func , req , pkt ) ;
if ( ! sp ) {
ql_dbg ( ql_dbg_edif , v , 0x3063 ,
" %s: no sp found for pkt \n " , __func__ ) ;
return ;
}
/* use sp->vha due to npiv */
vha = sp - > vha ;
switch ( pkt - > flags & ( SA_FLAG_INVALIDATE | SA_FLAG_TX ) ) {
case 0 :
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , pkt - > sa_index ) ;
break ;
case 1 :
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , pkt - > sa_index ) ;
break ;
case 2 :
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , pkt - > sa_index ) ;
break ;
case 3 :
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d \n " ,
__func__ , vha , pkt - > sa_index ) ;
break ;
}
/*
* dig the nport handle out of the iocb , fcport - > loop_id can not be trusted
* to be correct during cleanup sa_update iocbs .
*/
nport_handle = sp - > fcport - > loop_id ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: %8phN comp status=%x old_sa_info=%x new_sa_info=%x lid %d, index=0x%x pkt_flags %xh hdl=%x \n " ,
__func__ , sp - > fcport - > port_name , pkt - > u . comp_sts , pkt - > old_sa_info , pkt - > new_sa_info ,
nport_handle , pkt - > sa_index , pkt - > flags , sp - > handle ) ;
/* if rx delete, remove the timer */
if ( ( pkt - > flags & ( SA_FLAG_INVALIDATE | SA_FLAG_TX ) ) = = SA_FLAG_INVALIDATE ) {
struct edif_list_entry * edif_entry ;
sp - > fcport - > flags & = ~ ( FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE ) ;
edif_entry = qla_edif_list_find_sa_index ( sp - > fcport , nport_handle ) ;
if ( edif_entry ) {
ql_dbg ( ql_dbg_edif , vha , 0x5033 ,
" %s: removing edif_entry %p, new sa_index: 0x%x \n " ,
__func__ , edif_entry , pkt - > sa_index ) ;
qla_edif_list_delete_sa_index ( sp - > fcport , edif_entry ) ;
2022-12-20 13:45:19 -05:00
timer_shutdown ( & edif_entry - > timer ) ;
2021-06-23 22:26:00 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x5033 ,
" %s: releasing edif_entry %p, new sa_index: 0x%x \n " ,
__func__ , edif_entry , pkt - > sa_index ) ;
kfree ( edif_entry ) ;
}
}
/*
* if this is a delete for either tx or rx , make sure it succeeded .
* The new_sa_info field should be 0xffff on success
*/
if ( pkt - > flags & SA_FLAG_INVALIDATE )
old_sa_deleted = ( le16_to_cpu ( pkt - > new_sa_info ) = = 0xffff ) ? 1 : 0 ;
/* Process update and delete the same way */
/* If this is an sadb cleanup delete, bypass sending events to IPSEC */
if ( sp - > flags & SRB_EDIF_CLEANUP_DELETE ) {
sp - > fcport - > flags & = ~ ( FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: nph 0x%x, sa_index %d removed from fw \n " ,
__func__ , sp - > fcport - > loop_id , pkt - > sa_index ) ;
} else if ( ( pkt - > entry_status = = 0 ) & & ( pkt - > u . comp_sts = = 0 ) & &
old_sa_deleted ) {
/*
* Note : Wa are only keeping track of latest SA ,
* so we know when we can start enableing encryption per I / O .
* If all SA ' s get deleted , let FW reject the IOCB .
* TODO : edif : don ' t set enabled here I think
* TODO : edif : prli complete is where it should be set
*/
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x3063 ,
" SA(%x)updated for s_id %02x%02x%02x \n " ,
pkt - > new_sa_info ,
pkt - > port_id [ 2 ] , pkt - > port_id [ 1 ] , pkt - > port_id [ 0 ] ) ;
sp - > fcport - > edif . enable = 1 ;
if ( pkt - > flags & SA_FLAG_TX ) {
sp - > fcport - > edif . tx_sa_set = 1 ;
sp - > fcport - > edif . tx_sa_pending = 0 ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( vha , VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
QL_VND_SA_STAT_SUCCESS ,
QL_VND_TX_SA_KEY , sp - > fcport ) ;
2021-06-23 22:26:00 -07:00
} else {
sp - > fcport - > edif . rx_sa_set = 1 ;
sp - > fcport - > edif . rx_sa_pending = 0 ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( vha , VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
QL_VND_SA_STAT_SUCCESS ,
QL_VND_RX_SA_KEY , sp - > fcport ) ;
2021-06-23 22:26:00 -07:00
}
} else {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: %8phN SA update FAILED: sa_index: %d, new_sa_info %d, %02x%02x%02x \n " ,
__func__ , sp - > fcport - > port_name , pkt - > sa_index , pkt - > new_sa_info ,
pkt - > port_id [ 2 ] , pkt - > port_id [ 1 ] , pkt - > port_id [ 0 ] ) ;
2021-06-23 22:26:03 -07:00
if ( pkt - > flags & SA_FLAG_TX )
qla_edb_eventcreate ( vha , VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
( le16_to_cpu ( pkt - > u . comp_sts ) < < 16 ) | QL_VND_SA_STAT_FAILED ,
QL_VND_TX_SA_KEY , sp - > fcport ) ;
else
qla_edb_eventcreate ( vha , VND_CMD_AUTH_STATE_SAUPDATE_COMPL ,
( le16_to_cpu ( pkt - > u . comp_sts ) < < 16 ) | QL_VND_SA_STAT_FAILED ,
QL_VND_RX_SA_KEY , sp - > fcport ) ;
2021-06-23 22:26:00 -07:00
}
/* for delete, release sa_ctl, sa_index */
if ( pkt - > flags & SA_FLAG_INVALIDATE ) {
/* release the sa_ctl */
sa_ctl = qla_edif_find_sa_ctl_by_index ( sp - > fcport ,
le16_to_cpu ( pkt - > sa_index ) , ( pkt - > flags & SA_FLAG_TX ) ) ;
if ( sa_ctl & &
qla_edif_find_sa_ctl_by_index ( sp - > fcport , sa_ctl - > index ,
( pkt - > flags & SA_FLAG_TX ) ) ! = NULL ) {
ql_dbg ( ql_dbg_edif + ql_dbg_verbose , vha , 0x3063 ,
" %s: freeing sa_ctl for index %d \n " ,
__func__ , sa_ctl - > index ) ;
qla_edif_free_sa_ctl ( sp - > fcport , sa_ctl , sa_ctl - > index ) ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sa_ctl NOT freed, sa_ctl: %p \n " ,
__func__ , sa_ctl ) ;
}
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_index %d, nph: 0x%x \n " ,
__func__ , le16_to_cpu ( pkt - > sa_index ) , nport_handle ) ;
qla_edif_sadb_delete_sa_index ( sp - > fcport , nport_handle ,
le16_to_cpu ( pkt - > sa_index ) ) ;
/*
* check for a failed sa_update and remove
* the sadb entry .
*/
} else if ( pkt - > u . comp_sts ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: freeing sa_index %d, nph: 0x%x \n " ,
__func__ , pkt - > sa_index , nport_handle ) ;
qla_edif_sadb_delete_sa_index ( sp - > fcport , nport_handle ,
le16_to_cpu ( pkt - > sa_index ) ) ;
2021-08-16 22:13:04 -07:00
switch ( le16_to_cpu ( pkt - > u . comp_sts ) ) {
case CS_PORT_EDIF_UNAVAIL :
case CS_PORT_EDIF_LOGOUT :
qlt_schedule_sess_for_deletion ( sp - > fcport ) ;
break ;
default :
break ;
}
2021-06-23 22:26:00 -07:00
}
sp - > done ( sp , 0 ) ;
}
2021-06-23 22:26:04 -07:00
/**
* qla28xx_start_scsi_edif ( ) - Send a SCSI type 6 command to the ISP
* @ sp : command to send to the ISP
*
* Return : non - zero if a failure occurred , else zero .
*/
int
qla28xx_start_scsi_edif ( srb_t * sp )
{
int nseg ;
unsigned long flags ;
struct scsi_cmnd * cmd ;
uint32_t * clr_ptr ;
uint32_t index , i ;
uint32_t handle ;
uint16_t cnt ;
int16_t req_cnt ;
uint16_t tot_dsds ;
__be32 * fcp_dl ;
uint8_t additional_cdb_len ;
struct ct6_dsd * ctx ;
struct scsi_qla_host * vha = sp - > vha ;
struct qla_hw_data * ha = vha - > hw ;
struct cmd_type_6 * cmd_pkt ;
struct dsd64 * cur_dsd ;
uint8_t avail_dsds = 0 ;
struct scatterlist * sg ;
struct req_que * req = sp - > qpair - > req ;
spinlock_t * lock = sp - > qpair - > qp_lock_ptr ;
/* Setup device pointers. */
cmd = GET_CMD_SP ( sp ) ;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0 ;
/* Send marker if required */
if ( vha - > marker_needed ! = 0 ) {
if ( qla2x00_marker ( vha , sp - > qpair , 0 , 0 , MK_SYNC_ALL ) ! =
QLA_SUCCESS ) {
ql_log ( ql_log_warn , vha , 0x300c ,
" qla2x00_marker failed for cmd=%p. \n " , cmd ) ;
return QLA_FUNCTION_FAILED ;
}
vha - > marker_needed = 0 ;
}
/* Acquire ring specific lock */
spin_lock_irqsave ( lock , flags ) ;
/* Check for room in outstanding command list. */
handle = req - > current_outstanding_cmd ;
for ( index = 1 ; index < req - > num_outstanding_cmds ; index + + ) {
handle + + ;
if ( handle = = req - > num_outstanding_cmds )
handle = 1 ;
if ( ! req - > outstanding_cmds [ handle ] )
break ;
}
if ( index = = req - > num_outstanding_cmds )
goto queuing_error ;
/* Map the sg table so we have an accurate count of sg entries needed */
if ( scsi_sg_count ( cmd ) ) {
nseg = dma_map_sg ( & ha - > pdev - > dev , scsi_sglist ( cmd ) ,
scsi_sg_count ( cmd ) , cmd - > sc_data_direction ) ;
if ( unlikely ( ! nseg ) )
goto queuing_error ;
} else {
nseg = 0 ;
}
tot_dsds = nseg ;
req_cnt = qla24xx_calc_iocbs ( vha , tot_dsds ) ;
2022-06-08 04:58:40 -07:00
2022-12-19 03:07:41 -08:00
sp - > iores . res_type = RESOURCE_IOCB | RESOURCE_EXCH ;
sp - > iores . exch_cnt = 1 ;
2022-06-08 04:58:40 -07:00
sp - > iores . iocb_cnt = req_cnt ;
2022-12-19 03:07:41 -08:00
if ( qla_get_fw_resources ( sp - > qpair , & sp - > iores ) )
2022-06-08 04:58:40 -07:00
goto queuing_error ;
2021-06-23 22:26:04 -07:00
if ( req - > cnt < ( req_cnt + 2 ) ) {
cnt = IS_SHADOW_REG_CAPABLE ( ha ) ? * req - > out_ptr :
rd_reg_dword ( req - > req_q_out ) ;
if ( req - > ring_index < cnt )
req - > cnt = cnt - req - > ring_index ;
else
req - > cnt = req - > length -
( req - > ring_index - cnt ) ;
if ( req - > cnt < ( req_cnt + 2 ) )
goto queuing_error ;
}
2022-12-21 20:39:28 -08:00
if ( qla_get_buf ( vha , sp - > qpair , & sp - > u . scmd . buf_dsc ) ) {
2021-06-23 22:26:04 -07:00
ql_log ( ql_log_fatal , vha , 0x3011 ,
2022-12-21 20:39:28 -08:00
" Failed to allocate buf for fcp_cmnd for cmd=%p. \n " , cmd ) ;
2021-06-23 22:26:04 -07:00
goto queuing_error ;
}
2022-12-21 20:39:28 -08:00
sp - > flags | = SRB_GOT_BUF ;
ctx = & sp - > u . scmd . ct6_ctx ;
ctx - > fcp_cmnd = sp - > u . scmd . buf_dsc . buf ;
ctx - > fcp_cmnd_dma = sp - > u . scmd . buf_dsc . buf_dma ;
2021-06-23 22:26:04 -07:00
if ( cmd - > cmd_len > 16 ) {
additional_cdb_len = cmd - > cmd_len - 16 ;
if ( ( cmd - > cmd_len % 4 ) ! = 0 ) {
/*
* SCSI command bigger than 16 bytes must be
* multiple of 4
*/
ql_log ( ql_log_warn , vha , 0x3012 ,
" scsi cmd len %d not multiple of 4 for cmd=%p. \n " ,
cmd - > cmd_len , cmd ) ;
goto queuing_error_fcp_cmnd ;
}
ctx - > fcp_cmnd_len = 12 + cmd - > cmd_len + 4 ;
} else {
additional_cdb_len = 0 ;
ctx - > fcp_cmnd_len = 12 + 16 + 4 ;
}
cmd_pkt = ( struct cmd_type_6 * ) req - > ring_ptr ;
cmd_pkt - > handle = make_handle ( req - > id , handle ) ;
/*
* Zero out remaining portion of packet .
* tagged queuing modifier - - default is TSK_SIMPLE ( 0 ) .
*/
clr_ptr = ( uint32_t * ) cmd_pkt + 2 ;
memset ( clr_ptr , 0 , REQUEST_ENTRY_SIZE - 8 ) ;
cmd_pkt - > dseg_count = cpu_to_le16 ( tot_dsds ) ;
/* No data transfer */
if ( ! scsi_bufflen ( cmd ) | | cmd - > sc_data_direction = = DMA_NONE ) {
cmd_pkt - > byte_count = cpu_to_le32 ( 0 ) ;
goto no_dsds ;
}
/* Set transfer direction */
if ( cmd - > sc_data_direction = = DMA_TO_DEVICE ) {
cmd_pkt - > control_flags = cpu_to_le16 ( CF_WRITE_DATA ) ;
vha - > qla_stats . output_bytes + = scsi_bufflen ( cmd ) ;
vha - > qla_stats . output_requests + + ;
sp - > fcport - > edif . tx_bytes + = scsi_bufflen ( cmd ) ;
} else if ( cmd - > sc_data_direction = = DMA_FROM_DEVICE ) {
cmd_pkt - > control_flags = cpu_to_le16 ( CF_READ_DATA ) ;
vha - > qla_stats . input_bytes + = scsi_bufflen ( cmd ) ;
vha - > qla_stats . input_requests + + ;
sp - > fcport - > edif . rx_bytes + = scsi_bufflen ( cmd ) ;
}
cmd_pkt - > control_flags | = cpu_to_le16 ( CF_EN_EDIF ) ;
cmd_pkt - > control_flags & = ~ ( cpu_to_le16 ( CF_NEW_SA ) ) ;
/* One DSD is available in the Command Type 6 IOCB */
avail_dsds = 1 ;
cur_dsd = & cmd_pkt - > fcp_dsd ;
/* Load data segments */
scsi_for_each_sg ( cmd , sg , tot_dsds , i ) {
dma_addr_t sle_dma ;
cont_a64_entry_t * cont_pkt ;
/* Allocate additional continuation packets? */
if ( avail_dsds = = 0 ) {
/*
* Five DSDs are available in the Continuation
* Type 1 IOCB .
*/
cont_pkt = qla2x00_prep_cont_type1_iocb ( vha , req ) ;
cur_dsd = cont_pkt - > dsd ;
avail_dsds = 5 ;
}
sle_dma = sg_dma_address ( sg ) ;
put_unaligned_le64 ( sle_dma , & cur_dsd - > address ) ;
cur_dsd - > length = cpu_to_le32 ( sg_dma_len ( sg ) ) ;
cur_dsd + + ;
avail_dsds - - ;
}
no_dsds :
/* Set NPORT-ID and LUN number*/
cmd_pkt - > nport_handle = cpu_to_le16 ( sp - > fcport - > loop_id ) ;
cmd_pkt - > port_id [ 0 ] = sp - > fcport - > d_id . b . al_pa ;
cmd_pkt - > port_id [ 1 ] = sp - > fcport - > d_id . b . area ;
cmd_pkt - > port_id [ 2 ] = sp - > fcport - > d_id . b . domain ;
cmd_pkt - > vp_index = sp - > vha - > vp_idx ;
cmd_pkt - > entry_type = COMMAND_TYPE_6 ;
/* Set total data segment count. */
cmd_pkt - > entry_count = ( uint8_t ) req_cnt ;
int_to_scsilun ( cmd - > device - > lun , & cmd_pkt - > lun ) ;
host_to_fcp_swap ( ( uint8_t * ) & cmd_pkt - > lun , sizeof ( cmd_pkt - > lun ) ) ;
/* build FCP_CMND IU */
int_to_scsilun ( cmd - > device - > lun , & ctx - > fcp_cmnd - > lun ) ;
ctx - > fcp_cmnd - > additional_cdb_len = additional_cdb_len ;
if ( cmd - > sc_data_direction = = DMA_TO_DEVICE )
ctx - > fcp_cmnd - > additional_cdb_len | = 1 ;
else if ( cmd - > sc_data_direction = = DMA_FROM_DEVICE )
ctx - > fcp_cmnd - > additional_cdb_len | = 2 ;
/* Populate the FCP_PRIO. */
if ( ha - > flags . fcp_prio_enabled )
ctx - > fcp_cmnd - > task_attribute | =
sp - > fcport - > fcp_prio < < 3 ;
memcpy ( ctx - > fcp_cmnd - > cdb , cmd - > cmnd , cmd - > cmd_len ) ;
fcp_dl = ( __be32 * ) ( ctx - > fcp_cmnd - > cdb + 16 +
additional_cdb_len ) ;
* fcp_dl = htonl ( ( uint32_t ) scsi_bufflen ( cmd ) ) ;
cmd_pkt - > fcp_cmnd_dseg_len = cpu_to_le16 ( ctx - > fcp_cmnd_len ) ;
put_unaligned_le64 ( ctx - > fcp_cmnd_dma , & cmd_pkt - > fcp_cmnd_dseg_address ) ;
cmd_pkt - > byte_count = cpu_to_le32 ( ( uint32_t ) scsi_bufflen ( cmd ) ) ;
/* Set total data segment count. */
cmd_pkt - > entry_count = ( uint8_t ) req_cnt ;
cmd_pkt - > entry_status = 0 ;
/* Build command packet. */
req - > current_outstanding_cmd = handle ;
req - > outstanding_cmds [ handle ] = sp ;
sp - > handle = handle ;
cmd - > host_scribble = ( unsigned char * ) ( unsigned long ) handle ;
req - > cnt - = req_cnt ;
/* Adjust ring index. */
wmb ( ) ;
req - > ring_index + + ;
if ( req - > ring_index = = req - > length ) {
req - > ring_index = 0 ;
req - > ring_ptr = req - > ring ;
} else {
req - > ring_ptr + + ;
}
2021-06-23 22:26:05 -07:00
sp - > qpair - > cmd_cnt + + ;
2021-06-23 22:26:04 -07:00
/* Set chip new ring index. */
wrt_reg_dword ( req - > req_q_in , req - > ring_index ) ;
spin_unlock_irqrestore ( lock , flags ) ;
return QLA_SUCCESS ;
queuing_error_fcp_cmnd :
queuing_error :
if ( tot_dsds )
scsi_dma_unmap ( cmd ) ;
2022-12-21 20:39:28 -08:00
qla_put_buf ( sp - > qpair , & sp - > u . scmd . buf_dsc ) ;
2022-12-19 03:07:41 -08:00
qla_put_fw_resources ( sp - > qpair , & sp - > iores ) ;
2021-06-23 22:26:04 -07:00
spin_unlock_irqrestore ( lock , flags ) ;
return QLA_FUNCTION_FAILED ;
}
2021-06-23 22:26:02 -07:00
/**********************************************
* edif update / delete sa_index list functions *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* clear the edif_indx_list for this port */
void qla_edif_list_del ( fc_port_t * fcport )
{
struct edif_list_entry * indx_lst ;
struct edif_list_entry * tindx_lst ;
struct list_head * indx_list = & fcport - > edif . edif_indx_list ;
unsigned long flags = 0 ;
spin_lock_irqsave ( & fcport - > edif . indx_list_lock , flags ) ;
list_for_each_entry_safe ( indx_lst , tindx_lst , indx_list , next ) {
list_del ( & indx_lst - > next ) ;
kfree ( indx_lst ) ;
}
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
}
2021-06-23 22:26:00 -07:00
/******************
* SADB functions *
* * * * * * * * * * * * * * * * * */
/* allocate/retrieve an sa_index for a given spi */
static uint16_t qla_edif_sadb_get_sa_index ( fc_port_t * fcport ,
struct qla_sa_update_frame * sa_frame )
{
struct edif_sa_index_entry * entry ;
struct list_head * sa_list ;
uint16_t sa_index ;
int dir = sa_frame - > flags & SAU_FLG_TX ;
int slot = 0 ;
int free_slot = - 1 ;
scsi_qla_host_t * vha = fcport - > vha ;
struct qla_hw_data * ha = vha - > hw ;
unsigned long flags = 0 ;
uint16_t nport_handle = fcport - > loop_id ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: entry fc_port: %p, nport_handle: 0x%x \n " ,
__func__ , fcport , nport_handle ) ;
if ( dir )
sa_list = & ha - > sadb_tx_index_list ;
else
sa_list = & ha - > sadb_rx_index_list ;
entry = qla_edif_sadb_find_sa_index_entry ( nport_handle , sa_list ) ;
if ( ! entry ) {
if ( ( sa_frame - > flags & ( SAU_FLG_TX | SAU_FLG_INV ) ) = = SAU_FLG_INV ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: rx delete request with no entry \n " , __func__ ) ;
return RX_DELETE_NO_EDIF_SA_INDEX ;
}
/* if there is no entry for this nport, add one */
entry = kzalloc ( ( sizeof ( struct edif_sa_index_entry ) ) , GFP_ATOMIC ) ;
if ( ! entry )
return INVALID_EDIF_SA_INDEX ;
sa_index = qla_edif_get_sa_index_from_freepool ( fcport , dir ) ;
if ( sa_index = = INVALID_EDIF_SA_INDEX ) {
kfree ( entry ) ;
return INVALID_EDIF_SA_INDEX ;
}
INIT_LIST_HEAD ( & entry - > next ) ;
entry - > handle = nport_handle ;
entry - > fcport = fcport ;
entry - > sa_pair [ 0 ] . spi = sa_frame - > spi ;
entry - > sa_pair [ 0 ] . sa_index = sa_index ;
entry - > sa_pair [ 1 ] . spi = 0 ;
entry - > sa_pair [ 1 ] . sa_index = INVALID_EDIF_SA_INDEX ;
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
list_add_tail ( & entry - > next , sa_list ) ;
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: Created new sadb entry for nport_handle 0x%x, spi 0x%x, returning sa_index %d \n " ,
__func__ , nport_handle , sa_frame - > spi , sa_index ) ;
return sa_index ;
}
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
/* see if we already have an entry for this spi */
for ( slot = 0 ; slot < 2 ; slot + + ) {
if ( entry - > sa_pair [ slot ] . sa_index = = INVALID_EDIF_SA_INDEX ) {
free_slot = slot ;
} else {
if ( entry - > sa_pair [ slot ] . spi = = sa_frame - > spi ) {
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: sadb slot %d entry for lid 0x%x, spi 0x%x found, sa_index %d \n " ,
__func__ , slot , entry - > handle , sa_frame - > spi ,
entry - > sa_pair [ slot ] . sa_index ) ;
return entry - > sa_pair [ slot ] . sa_index ;
}
}
}
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
/* both slots are used */
if ( free_slot = = - 1 ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: WARNING: No free slots in sadb for nport_handle 0x%x, spi: 0x%x \n " ,
__func__ , entry - > handle , sa_frame - > spi ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: Slot 0 spi: 0x%x sa_index: %d, Slot 1 spi: 0x%x sa_index: %d \n " ,
__func__ , entry - > sa_pair [ 0 ] . spi , entry - > sa_pair [ 0 ] . sa_index ,
entry - > sa_pair [ 1 ] . spi , entry - > sa_pair [ 1 ] . sa_index ) ;
return INVALID_EDIF_SA_INDEX ;
}
/* there is at least one free slot, use it */
sa_index = qla_edif_get_sa_index_from_freepool ( fcport , dir ) ;
if ( sa_index = = INVALID_EDIF_SA_INDEX ) {
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x3063 ,
" %s: empty freepool!! \n " , __func__ ) ;
return INVALID_EDIF_SA_INDEX ;
}
spin_lock_irqsave ( & ha - > sadb_lock , flags ) ;
entry - > sa_pair [ free_slot ] . spi = sa_frame - > spi ;
entry - > sa_pair [ free_slot ] . sa_index = sa_index ;
spin_unlock_irqrestore ( & ha - > sadb_lock , flags ) ;
ql_dbg ( ql_dbg_edif , fcport - > vha , 0x3063 ,
" %s: sadb slot %d entry for nport_handle 0x%x, spi 0x%x added, returning sa_index %d \n " ,
__func__ , free_slot , entry - > handle , sa_frame - > spi , sa_index ) ;
return sa_index ;
}
/* release any sadb entries -- only done at teardown */
void qla_edif_sadb_release ( struct qla_hw_data * ha )
{
2021-10-26 04:54:06 -07:00
struct edif_sa_index_entry * entry , * tmp ;
2021-06-23 22:26:00 -07:00
2021-10-26 04:54:06 -07:00
list_for_each_entry_safe ( entry , tmp , & ha - > sadb_rx_index_list , next ) {
2021-06-23 22:26:00 -07:00
list_del ( & entry - > next ) ;
kfree ( entry ) ;
}
2021-10-26 04:54:06 -07:00
list_for_each_entry_safe ( entry , tmp , & ha - > sadb_tx_index_list , next ) {
2021-06-23 22:26:00 -07:00
list_del ( & entry - > next ) ;
kfree ( entry ) ;
}
}
/**************************
* sadb freepool functions
* * * * * * * * * * * * * * * * * * * * * * * * * */
/* build the rx and tx sa_index free pools -- only done at fcport init */
int qla_edif_sadb_build_free_pool ( struct qla_hw_data * ha )
{
ha - > edif_tx_sa_id_map =
kcalloc ( BITS_TO_LONGS ( EDIF_NUM_SA_INDEX ) , sizeof ( long ) , GFP_KERNEL ) ;
if ( ! ha - > edif_tx_sa_id_map ) {
ql_log_pci ( ql_log_fatal , ha - > pdev , 0x0009 ,
" Unable to allocate memory for sadb tx. \n " ) ;
return - ENOMEM ;
}
ha - > edif_rx_sa_id_map =
kcalloc ( BITS_TO_LONGS ( EDIF_NUM_SA_INDEX ) , sizeof ( long ) , GFP_KERNEL ) ;
if ( ! ha - > edif_rx_sa_id_map ) {
kfree ( ha - > edif_tx_sa_id_map ) ;
ha - > edif_tx_sa_id_map = NULL ;
ql_log_pci ( ql_log_fatal , ha - > pdev , 0x0009 ,
" Unable to allocate memory for sadb rx. \n " ) ;
return - ENOMEM ;
}
return 0 ;
}
/* release the free pool - only done during fcport teardown */
void qla_edif_sadb_release_free_pool ( struct qla_hw_data * ha )
{
kfree ( ha - > edif_tx_sa_id_map ) ;
ha - > edif_tx_sa_id_map = NULL ;
kfree ( ha - > edif_rx_sa_id_map ) ;
ha - > edif_rx_sa_id_map = NULL ;
}
static void __chk_edif_rx_sa_delete_pending ( scsi_qla_host_t * vha ,
fc_port_t * fcport , uint32_t handle , uint16_t sa_index )
{
struct edif_list_entry * edif_entry ;
struct edif_sa_ctl * sa_ctl ;
uint16_t delete_sa_index = INVALID_EDIF_SA_INDEX ;
unsigned long flags = 0 ;
uint16_t nport_handle = fcport - > loop_id ;
uint16_t cached_nport_handle ;
spin_lock_irqsave ( & fcport - > edif . indx_list_lock , flags ) ;
edif_entry = qla_edif_list_find_sa_index ( fcport , nport_handle ) ;
if ( ! edif_entry ) {
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
return ; /* no pending delete for this handle */
}
/*
* check for no pending delete for this index or iocb does not
* match rx sa_index
*/
if ( edif_entry - > delete_sa_index = = INVALID_EDIF_SA_INDEX | |
edif_entry - > update_sa_index ! = sa_index ) {
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
return ;
}
/*
* wait until we have seen at least EDIF_DELAY_COUNT transfers before
* queueing RX delete
*/
if ( edif_entry - > count + + < EDIF_RX_DELETE_FILTER_COUNT ) {
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
return ;
}
ql_dbg ( ql_dbg_edif , vha , 0x5033 ,
" %s: invalidating delete_sa_index, update_sa_index: 0x%x sa_index: 0x%x, delete_sa_index: 0x%x \n " ,
__func__ , edif_entry - > update_sa_index , sa_index , edif_entry - > delete_sa_index ) ;
delete_sa_index = edif_entry - > delete_sa_index ;
edif_entry - > delete_sa_index = INVALID_EDIF_SA_INDEX ;
cached_nport_handle = edif_entry - > handle ;
spin_unlock_irqrestore ( & fcport - > edif . indx_list_lock , flags ) ;
/* sanity check on the nport handle */
if ( nport_handle ! = cached_nport_handle ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: POST SA DELETE nport_handle mismatch: lid: 0x%x, edif_entry nph: 0x%x \n " ,
__func__ , nport_handle , cached_nport_handle ) ;
}
/* find the sa_ctl for the delete and schedule the delete */
sa_ctl = qla_edif_find_sa_ctl_by_index ( fcport , delete_sa_index , 0 ) ;
if ( sa_ctl ) {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: POST SA DELETE sa_ctl: %p, index recvd %d \n " ,
__func__ , sa_ctl , sa_index ) ;
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" delete index %d, update index: %d, nport handle: 0x%x, handle: 0x%x \n " ,
delete_sa_index ,
edif_entry - > update_sa_index , nport_handle , handle ) ;
sa_ctl - > flags = EDIF_SA_CTL_FLG_DEL ;
set_bit ( EDIF_SA_CTL_REPL , & sa_ctl - > state ) ;
qla_post_sa_replace_work ( fcport - > vha , fcport ,
nport_handle , sa_ctl ) ;
} else {
ql_dbg ( ql_dbg_edif , vha , 0x3063 ,
" %s: POST SA DELETE sa_ctl not found for delete_sa_index: %d \n " ,
__func__ , delete_sa_index ) ;
}
}
void qla_chk_edif_rx_sa_delete_pending ( scsi_qla_host_t * vha ,
srb_t * sp , struct sts_entry_24xx * sts24 )
{
fc_port_t * fcport = sp - > fcport ;
/* sa_index used by this iocb */
struct scsi_cmnd * cmd = GET_CMD_SP ( sp ) ;
uint32_t handle ;
handle = ( uint32_t ) LSW ( sts24 - > handle ) ;
/* find out if this status iosb is for a scsi read */
if ( cmd - > sc_data_direction ! = DMA_FROM_DEVICE )
return ;
return __chk_edif_rx_sa_delete_pending ( vha , fcport , handle ,
le16_to_cpu ( sts24 - > edif_sa_index ) ) ;
}
void qlt_chk_edif_rx_sa_delete_pending ( scsi_qla_host_t * vha , fc_port_t * fcport ,
struct ctio7_from_24xx * pkt )
{
__chk_edif_rx_sa_delete_pending ( vha , fcport ,
pkt - > handle , le16_to_cpu ( pkt - > edif_sa_index ) ) ;
}
2021-06-23 22:25:58 -07:00
static void qla_parse_auth_els_ctl ( struct srb * sp )
{
struct qla_els_pt_arg * a = & sp - > u . bsg_cmd . u . els_arg ;
struct bsg_job * bsg_job = sp - > u . bsg_cmd . bsg_job ;
struct fc_bsg_request * request = bsg_job - > request ;
struct qla_bsg_auth_els_request * p =
( struct qla_bsg_auth_els_request * ) bsg_job - > request ;
a - > tx_len = a - > tx_byte_count = sp - > remap . req . len ;
a - > tx_addr = sp - > remap . req . dma ;
a - > rx_len = a - > rx_byte_count = sp - > remap . rsp . len ;
a - > rx_addr = sp - > remap . rsp . dma ;
if ( p - > e . sub_cmd = = SEND_ELS_REPLY ) {
a - > control_flags = p - > e . extra_control_flags < < 13 ;
a - > rx_xchg_address = cpu_to_le32 ( p - > e . extra_rx_xchg_address ) ;
if ( p - > e . extra_control_flags = = BSG_CTL_FLAG_LS_ACC )
a - > els_opcode = ELS_LS_ACC ;
else if ( p - > e . extra_control_flags = = BSG_CTL_FLAG_LS_RJT )
a - > els_opcode = ELS_LS_RJT ;
}
a - > did = sp - > fcport - > d_id ;
a - > els_opcode = request - > rqst_data . h_els . command_code ;
a - > nport_handle = cpu_to_le16 ( sp - > fcport - > loop_id ) ;
a - > vp_idx = sp - > vha - > vp_idx ;
}
int qla_edif_process_els ( scsi_qla_host_t * vha , struct bsg_job * bsg_job )
{
struct fc_bsg_request * bsg_request = bsg_job - > request ;
struct fc_bsg_reply * bsg_reply = bsg_job - > reply ;
fc_port_t * fcport = NULL ;
struct qla_hw_data * ha = vha - > hw ;
srb_t * sp ;
2022-06-06 21:46:23 -07:00
int rval = ( DID_ERROR < < 16 ) , cnt ;
2021-06-23 22:25:58 -07:00
port_id_t d_id ;
struct qla_bsg_auth_els_request * p =
( struct qla_bsg_auth_els_request * ) bsg_job - > request ;
2022-06-06 21:46:18 -07:00
struct qla_bsg_auth_els_reply * rpl =
( struct qla_bsg_auth_els_reply * ) bsg_job - > reply ;
rpl - > version = EDIF_VERSION1 ;
2021-06-23 22:25:58 -07:00
d_id . b . al_pa = bsg_request - > rqst_data . h_els . port_id [ 2 ] ;
d_id . b . area = bsg_request - > rqst_data . h_els . port_id [ 1 ] ;
d_id . b . domain = bsg_request - > rqst_data . h_els . port_id [ 0 ] ;
/* find matching d_id in fcport list */
fcport = qla2x00_find_fcport_by_pid ( vha , & d_id ) ;
if ( ! fcport ) {
ql_dbg ( ql_dbg_edif , vha , 0x911a ,
" %s fcport not find online portid=%06x. \n " ,
__func__ , d_id . b24 ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_ERROR ) ;
return - EIO ;
}
if ( qla_bsg_check ( vha , bsg_job , fcport ) )
return 0 ;
2022-06-08 04:58:45 -07:00
if ( EDIF_SESS_DELETE ( fcport ) ) {
2021-06-23 22:25:58 -07:00
ql_dbg ( ql_dbg_edif , vha , 0x910d ,
" %s ELS code %x, no loop id. \n " , __func__ ,
bsg_request - > rqst_data . r_els . els_code ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_BAD_TARGET ) ;
return - ENXIO ;
}
if ( ! vha - > flags . online ) {
ql_log ( ql_log_warn , vha , 0x7005 , " Host not online. \n " ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_BAD_TARGET ) ;
rval = - EIO ;
goto done ;
}
/* pass through is supported only for ISP 4Gb or higher */
if ( ! IS_FWI2_CAPABLE ( ha ) ) {
ql_dbg ( ql_dbg_user , vha , 0x7001 ,
" ELS passthru not supported for ISP23xx based adapters. \n " ) ;
SET_DID_STATUS ( bsg_reply - > result , DID_BAD_TARGET ) ;
rval = - EPERM ;
goto done ;
}
sp = qla2x00_get_sp ( vha , fcport , GFP_KERNEL ) ;
if ( ! sp ) {
ql_dbg ( ql_dbg_user , vha , 0x7004 ,
" Failed get sp pid=%06x \n " , fcport - > d_id . b24 ) ;
rval = - ENOMEM ;
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
goto done ;
}
sp - > remap . req . len = bsg_job - > request_payload . payload_len ;
sp - > remap . req . buf = dma_pool_alloc ( ha - > purex_dma_pool ,
GFP_KERNEL , & sp - > remap . req . dma ) ;
if ( ! sp - > remap . req . buf ) {
ql_dbg ( ql_dbg_user , vha , 0x7005 ,
" Failed allocate request dma len=%x \n " ,
bsg_job - > request_payload . payload_len ) ;
rval = - ENOMEM ;
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
goto done_free_sp ;
}
sp - > remap . rsp . len = bsg_job - > reply_payload . payload_len ;
sp - > remap . rsp . buf = dma_pool_alloc ( ha - > purex_dma_pool ,
GFP_KERNEL , & sp - > remap . rsp . dma ) ;
if ( ! sp - > remap . rsp . buf ) {
ql_dbg ( ql_dbg_user , vha , 0x7006 ,
" Failed allocate response dma len=%x \n " ,
bsg_job - > reply_payload . payload_len ) ;
rval = - ENOMEM ;
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
goto done_free_remap_req ;
}
sg_copy_to_buffer ( bsg_job - > request_payload . sg_list ,
bsg_job - > request_payload . sg_cnt , sp - > remap . req . buf ,
sp - > remap . req . len ) ;
sp - > remap . remapped = true ;
sp - > type = SRB_ELS_CMD_HST_NOLOGIN ;
sp - > name = " SPCN_BSG_HST_NOLOGIN " ;
sp - > u . bsg_cmd . bsg_job = bsg_job ;
qla_parse_auth_els_ctl ( sp ) ;
sp - > free = qla2x00_bsg_sp_free ;
sp - > done = qla2x00_bsg_job_done ;
2022-06-06 21:46:23 -07:00
cnt = 0 ;
retry :
2021-06-23 22:25:58 -07:00
rval = qla2x00_start_sp ( sp ) ;
2022-06-06 21:46:23 -07:00
switch ( rval ) {
case QLA_SUCCESS :
ql_dbg ( ql_dbg_edif , vha , 0x700a ,
" %s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p \n " ,
__func__ , sc_to_str ( p - > e . sub_cmd ) , fcport - > port_name ,
p - > e . extra_rx_xchg_address , p - > e . extra_control_flags ,
sp - > handle , sp - > remap . req . len , bsg_job ) ;
break ;
case EAGAIN :
msleep ( EDIF_MSLEEP_INTERVAL ) ;
cnt + + ;
if ( cnt < EDIF_RETRY_COUNT )
goto retry ;
fallthrough ;
default :
2021-06-23 22:25:58 -07:00
ql_log ( ql_log_warn , vha , 0x700e ,
2022-06-06 21:46:23 -07:00
" %s qla2x00_start_sp failed = %d \n " , __func__ , rval ) ;
2021-06-23 22:25:58 -07:00
SET_DID_STATUS ( bsg_reply - > result , DID_IMM_RETRY ) ;
rval = - EIO ;
goto done_free_remap_rsp ;
}
return rval ;
done_free_remap_rsp :
dma_pool_free ( ha - > purex_dma_pool , sp - > remap . rsp . buf ,
sp - > remap . rsp . dma ) ;
done_free_remap_req :
dma_pool_free ( ha - > purex_dma_pool , sp - > remap . req . buf ,
sp - > remap . req . dma ) ;
done_free_sp :
qla2x00_rel_sp ( sp ) ;
done :
return rval ;
}
2021-06-23 22:26:02 -07:00
void qla_edif_sess_down ( struct scsi_qla_host * vha , struct fc_port * sess )
{
2022-06-06 21:46:19 -07:00
u16 cnt = 0 ;
2021-10-26 04:54:10 -07:00
if ( sess - > edif . app_sess_online & & DBELL_ACTIVE ( vha ) ) {
2021-06-23 22:26:02 -07:00
ql_dbg ( ql_dbg_disc , vha , 0xf09c ,
" %s: sess %8phN send port_offline event \n " ,
__func__ , sess - > port_name ) ;
sess - > edif . app_sess_online = 0 ;
2022-06-06 21:46:19 -07:00
sess - > edif . sess_down_acked = 0 ;
2021-06-23 22:26:03 -07:00
qla_edb_eventcreate ( vha , VND_CMD_AUTH_STATE_SESSION_SHUTDOWN ,
sess - > d_id . b24 , 0 , sess ) ;
2021-06-23 22:26:02 -07:00
qla2x00_post_aen_work ( vha , FCH_EVT_PORT_OFFLINE , sess - > d_id . b24 ) ;
2022-06-06 21:46:19 -07:00
while ( ! READ_ONCE ( sess - > edif . sess_down_acked ) & &
! test_bit ( VPORT_DELETE , & vha - > dpc_flags ) ) {
msleep ( 100 ) ;
cnt + + ;
if ( cnt > 100 )
break ;
}
sess - > edif . sess_down_acked = 0 ;
ql_dbg ( ql_dbg_disc , vha , 0xf09c ,
" %s: sess %8phN port_offline event completed \n " ,
__func__ , sess - > port_name ) ;
2021-06-23 22:26:02 -07:00
}
}
2021-10-26 04:54:05 -07:00
void qla_edif_clear_appdata ( struct scsi_qla_host * vha , struct fc_port * fcport )
{
if ( ! ( fcport - > flags & FCF_FCSP_DEVICE ) )
return ;
qla_edb_clear ( vha , fcport - > d_id ) ;
qla_enode_clear ( vha , fcport - > d_id ) ;
}