2005-04-17 02:20:36 +04:00
/*
2005-10-27 22:10:08 +04:00
* QLogic Fibre Channel HBA Driver
2014-04-12 00:54:24 +04:00
* Copyright ( c ) 2003 - 2014 QLogic Corporation
2005-04-17 02:20:36 +04:00
*
2005-10-27 22:10:08 +04:00
* See LICENSE . qla2xxx for copyright and licensing details .
2005-04-17 02:20:36 +04:00
*/
# include "qla_def.h"
2012-05-15 22:34:28 +04:00
# include "qla_target.h"
2014-09-25 13:16:46 +04:00
# include <linux/utsname.h>
2005-04-17 02:20:36 +04:00
static int qla2x00_sns_ga_nxt ( scsi_qla_host_t * , fc_port_t * ) ;
static int qla2x00_sns_gid_pt ( scsi_qla_host_t * , sw_info_t * ) ;
static int qla2x00_sns_gpn_id ( scsi_qla_host_t * , sw_info_t * ) ;
static int qla2x00_sns_gnn_id ( scsi_qla_host_t * , sw_info_t * ) ;
static int qla2x00_sns_rft_id ( scsi_qla_host_t * ) ;
static int qla2x00_sns_rnn_id ( scsi_qla_host_t * ) ;
2017-12-28 23:33:31 +03:00
static int qla_async_rftid ( scsi_qla_host_t * , port_id_t * ) ;
static int qla_async_rffid ( scsi_qla_host_t * , port_id_t * , u8 , u8 ) ;
static int qla_async_rnnid ( scsi_qla_host_t * , port_id_t * , u8 * ) ;
static int qla_async_rsnn_nn ( scsi_qla_host_t * ) ;
2005-04-17 02:20:36 +04:00
/**
2005-07-06 21:30:47 +04:00
* qla2x00_prep_ms_iocb ( ) - Prepare common MS / CT IOCB fields for SNS CT query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
* @ arg : CT arguments
2005-04-17 02:20:36 +04:00
*
2018-01-24 03:33:51 +03:00
* Returns a pointer to the @ vha ' s ms_iocb .
2005-04-17 02:20:36 +04:00
*/
2005-07-06 21:30:47 +04:00
void *
2017-01-20 09:28:00 +03:00
qla2x00_prep_ms_iocb ( scsi_qla_host_t * vha , struct ct_arg * arg )
2005-04-17 02:20:36 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
ms_iocb_entry_t * ms_pkt ;
2017-01-20 09:28:00 +03:00
ms_pkt = ( ms_iocb_entry_t * ) arg - > iocb ;
2005-04-17 02:20:36 +04:00
memset ( ms_pkt , 0 , sizeof ( ms_iocb_entry_t ) ) ;
ms_pkt - > entry_type = MS_IOCB_TYPE ;
ms_pkt - > entry_count = 1 ;
SET_TARGET_ID ( ha , ms_pkt - > loop_id , SIMPLE_NAME_SERVER ) ;
2015-07-09 17:24:08 +03:00
ms_pkt - > control_flags = cpu_to_le16 ( CF_READ | CF_HEAD_TAG ) ;
2008-02-29 01:06:11 +03:00
ms_pkt - > timeout = cpu_to_le16 ( ha - > r_a_tov / 10 * 2 ) ;
2015-07-09 17:24:08 +03:00
ms_pkt - > cmd_dsd_count = cpu_to_le16 ( 1 ) ;
ms_pkt - > total_dsd_count = cpu_to_le16 ( 2 ) ;
2017-01-20 09:28:00 +03:00
ms_pkt - > rsp_bytecount = cpu_to_le32 ( arg - > rsp_size ) ;
ms_pkt - > req_bytecount = cpu_to_le32 ( arg - > req_size ) ;
2005-04-17 02:20:36 +04:00
2017-01-20 09:28:00 +03:00
ms_pkt - > dseg_req_address [ 0 ] = cpu_to_le32 ( LSD ( arg - > req_dma ) ) ;
ms_pkt - > dseg_req_address [ 1 ] = cpu_to_le32 ( MSD ( arg - > req_dma ) ) ;
2005-04-17 02:20:36 +04:00
ms_pkt - > dseg_req_length = ms_pkt - > req_bytecount ;
2017-01-20 09:28:00 +03:00
ms_pkt - > dseg_rsp_address [ 0 ] = cpu_to_le32 ( LSD ( arg - > rsp_dma ) ) ;
ms_pkt - > dseg_rsp_address [ 1 ] = cpu_to_le32 ( MSD ( arg - > rsp_dma ) ) ;
2005-04-17 02:20:36 +04:00
ms_pkt - > dseg_rsp_length = ms_pkt - > rsp_bytecount ;
2013-08-27 09:37:40 +04:00
vha - > qla_stats . control_requests + + ;
2005-04-17 02:20:36 +04:00
return ( ms_pkt ) ;
}
2005-07-06 21:30:47 +04:00
/**
* qla24xx_prep_ms_iocb ( ) - Prepare common CT IOCB fields for SNS CT query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
* @ arg : CT arguments
2005-07-06 21:30:47 +04:00
*
* Returns a pointer to the @ ha ' s ms_iocb .
*/
void *
2017-01-20 09:28:00 +03:00
qla24xx_prep_ms_iocb ( scsi_qla_host_t * vha , struct ct_arg * arg )
2005-07-06 21:30:47 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-07-06 21:30:47 +04:00
struct ct_entry_24xx * ct_pkt ;
2017-01-20 09:28:00 +03:00
ct_pkt = ( struct ct_entry_24xx * ) arg - > iocb ;
2005-07-06 21:30:47 +04:00
memset ( ct_pkt , 0 , sizeof ( struct ct_entry_24xx ) ) ;
ct_pkt - > entry_type = CT_IOCB_TYPE ;
ct_pkt - > entry_count = 1 ;
2017-01-20 09:28:00 +03:00
ct_pkt - > nport_handle = cpu_to_le16 ( arg - > nport_handle ) ;
2008-02-29 01:06:11 +03:00
ct_pkt - > timeout = cpu_to_le16 ( ha - > r_a_tov / 10 * 2 ) ;
2015-07-09 17:24:08 +03:00
ct_pkt - > cmd_dsd_count = cpu_to_le16 ( 1 ) ;
ct_pkt - > rsp_dsd_count = cpu_to_le16 ( 1 ) ;
2017-01-20 09:28:00 +03:00
ct_pkt - > rsp_byte_count = cpu_to_le32 ( arg - > rsp_size ) ;
ct_pkt - > cmd_byte_count = cpu_to_le32 ( arg - > req_size ) ;
2005-07-06 21:30:47 +04:00
2017-01-20 09:28:00 +03:00
ct_pkt - > dseg_0_address [ 0 ] = cpu_to_le32 ( LSD ( arg - > req_dma ) ) ;
ct_pkt - > dseg_0_address [ 1 ] = cpu_to_le32 ( MSD ( arg - > req_dma ) ) ;
2005-07-06 21:30:47 +04:00
ct_pkt - > dseg_0_len = ct_pkt - > cmd_byte_count ;
2017-01-20 09:28:00 +03:00
ct_pkt - > dseg_1_address [ 0 ] = cpu_to_le32 ( LSD ( arg - > rsp_dma ) ) ;
ct_pkt - > dseg_1_address [ 1 ] = cpu_to_le32 ( MSD ( arg - > rsp_dma ) ) ;
2005-07-06 21:30:47 +04:00
ct_pkt - > dseg_1_len = ct_pkt - > rsp_byte_count ;
2008-11-06 21:40:19 +03:00
ct_pkt - > vp_index = vha - > vp_idx ;
2005-07-06 21:30:47 +04:00
2013-08-27 09:37:40 +04:00
vha - > qla_stats . control_requests + + ;
2005-07-06 21:30:47 +04:00
return ( ct_pkt ) ;
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_prep_ct_req ( ) - Prepare common CT request fields for SNS query .
2018-01-24 03:33:51 +03:00
* @ p : CT request buffer
2005-04-17 02:20:36 +04:00
* @ cmd : GS command
* @ rsp_size : response size in bytes
*
* Returns a pointer to the intitialized @ ct_req .
*/
static inline struct ct_sns_req *
2013-06-25 19:27:28 +04:00
qla2x00_prep_ct_req ( struct ct_sns_pkt * p , uint16_t cmd , uint16_t rsp_size )
2005-04-17 02:20:36 +04:00
{
2013-06-25 19:27:28 +04:00
memset ( p , 0 , sizeof ( struct ct_sns_pkt ) ) ;
2005-04-17 02:20:36 +04:00
2013-06-25 19:27:28 +04:00
p - > p . req . header . revision = 0x01 ;
p - > p . req . header . gs_type = 0xFC ;
p - > p . req . header . gs_subtype = 0x02 ;
p - > p . req . command = cpu_to_be16 ( cmd ) ;
p - > p . req . max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
2005-04-17 02:20:36 +04:00
2013-06-25 19:27:28 +04:00
return & p - > p . req ;
2005-04-17 02:20:36 +04:00
}
2017-01-20 09:28:00 +03:00
int
2008-11-06 21:40:19 +03:00
qla2x00_chk_ms_status ( scsi_qla_host_t * vha , ms_iocb_entry_t * ms_pkt ,
2005-07-06 21:30:47 +04:00
struct ct_sns_rsp * ct_rsp , const char * routine )
{
int rval ;
uint16_t comp_status ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2017-06-02 19:12:00 +03:00
bool lid_is_sns = false ;
2005-07-06 21:30:47 +04:00
rval = QLA_FUNCTION_FAILED ;
if ( ms_pkt - > entry_status ! = 0 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2031 ,
" %s failed, error status (%x) on port_id: %02x%02x%02x. \n " ,
routine , ms_pkt - > entry_status , vha - > d_id . b . domain ,
vha - > d_id . b . area , vha - > d_id . b . al_pa ) ;
2005-07-06 21:30:47 +04:00
} else {
2007-07-20 02:05:56 +04:00
if ( IS_FWI2_CAPABLE ( ha ) )
2006-12-14 06:20:26 +03:00
comp_status = le16_to_cpu (
( ( struct ct_entry_24xx * ) ms_pkt ) - > comp_status ) ;
2005-07-06 21:30:47 +04:00
else
comp_status = le16_to_cpu ( ms_pkt - > status ) ;
switch ( comp_status ) {
case CS_COMPLETE :
case CS_DATA_UNDERRUN :
case CS_DATA_OVERRUN : /* Overrun? */
if ( ct_rsp - > header . response ! =
2015-07-09 17:24:08 +03:00
cpu_to_be16 ( CT_ACCEPT_RESPONSE ) ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2077 ,
2017-04-01 00:37:04 +03:00
" %s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x \n " ,
2014-09-25 13:16:46 +04:00
routine , vha - > d_id . b . domain ,
vha - > d_id . b . area , vha - > d_id . b . al_pa ,
comp_status , ct_rsp - > header . response ) ;
2011-07-14 23:00:13 +04:00
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha ,
0x2078 , ( uint8_t * ) & ct_rsp - > header ,
sizeof ( struct ct_rsp_hdr ) ) ;
2006-12-14 06:20:28 +03:00
rval = QLA_INVALID_COMMAND ;
2005-07-06 21:30:47 +04:00
} else
rval = QLA_SUCCESS ;
break ;
2017-06-02 19:12:00 +03:00
case CS_PORT_LOGGED_OUT :
if ( IS_FWI2_CAPABLE ( ha ) ) {
if ( le16_to_cpu ( ms_pkt - > loop_id . extended ) = =
NPH_SNS )
lid_is_sns = true ;
} else {
if ( le16_to_cpu ( ms_pkt - > loop_id . extended ) = =
SIMPLE_NAME_SERVER )
lid_is_sns = true ;
}
if ( lid_is_sns ) {
ql_dbg ( ql_dbg_async , vha , 0x502b ,
" %s failed, Name server has logged out " ,
routine ) ;
rval = QLA_NOT_LOGGED_IN ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
}
break ;
2017-12-05 01:45:01 +03:00
case CS_TIMEOUT :
rval = QLA_FUNCTION_TIMEOUT ;
2017-12-08 03:02:46 +03:00
/* fall through */
2005-07-06 21:30:47 +04:00
default :
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2033 ,
" %s failed, completion status (%x) on port_id: "
" %02x%02x%02x. \n " , routine , comp_status ,
2011-02-24 02:27:09 +03:00
vha - > d_id . b . domain , vha - > d_id . b . area ,
2011-07-14 23:00:13 +04:00
vha - > d_id . b . al_pa ) ;
2005-07-06 21:30:47 +04:00
break ;
}
}
return rval ;
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_ga_nxt ( ) - SNS scan for fabric devices via GA_NXT command .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ fcport : fcport entry to updated
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_ga_nxt ( scsi_qla_host_t * vha , fc_port_t * fcport )
2005-04-17 02:20:36 +04:00
{
int rval ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_ga_nxt ( vha , fcport ) ;
2005-04-17 02:20:36 +04:00
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GA_NXT_REQ_SIZE ;
arg . rsp_size = GA_NXT_RSP_SIZE ;
arg . nport_handle = NPH_SNS ;
2005-04-17 02:20:36 +04:00
/* Issue GA_NXT */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GA_NXT_CMD ,
2005-04-17 02:20:36 +04:00
GA_NXT_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id */
ct_req - > req . port_id . port_id [ 0 ] = fcport - > d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = fcport - > d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = fcport - > d_id . b . al_pa ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-04-17 02:20:36 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2062 ,
" GA_NXT issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " GA_NXT " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Populate fc_port_t entry. */
fcport - > d_id . b . domain = ct_rsp - > rsp . ga_nxt . port_id [ 0 ] ;
fcport - > d_id . b . area = ct_rsp - > rsp . ga_nxt . port_id [ 1 ] ;
fcport - > d_id . b . al_pa = ct_rsp - > rsp . ga_nxt . port_id [ 2 ] ;
memcpy ( fcport - > node_name , ct_rsp - > rsp . ga_nxt . node_name ,
WWN_SIZE ) ;
memcpy ( fcport - > port_name , ct_rsp - > rsp . ga_nxt . port_name ,
WWN_SIZE ) ;
2012-11-21 11:40:30 +04:00
fcport - > fc4_type = ( ct_rsp - > rsp . ga_nxt . fc4_types [ 2 ] & BIT_0 ) ?
FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER ;
2005-04-17 02:20:36 +04:00
if ( ct_rsp - > rsp . ga_nxt . port_type ! = NS_N_PORT_TYPE & &
ct_rsp - > rsp . ga_nxt . port_type ! = NS_NL_PORT_TYPE )
fcport - > d_id . b . domain = 0xf0 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2063 ,
2013-08-27 09:37:27 +04:00
" GA_NXT entry - nn %8phN pn %8phN "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2013-08-27 09:37:27 +04:00
fcport - > node_name , fcport - > port_name ,
2005-04-17 02:20:36 +04:00
fcport - > d_id . b . domain , fcport - > d_id . b . area ,
2011-07-14 23:00:13 +04:00
fcport - > d_id . b . al_pa ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
2012-02-09 23:15:57 +04:00
static inline int
qla2x00_gid_pt_rsp_size ( scsi_qla_host_t * vha )
{
return vha - > hw - > max_fibre_devices * 4 + 16 ;
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_gid_pt ( ) - SNS scan for fabric devices via GID_PT command .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* NOTE : Non - Nx_Ports are not requested .
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_gid_pt ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
int rval ;
uint16_t i ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
struct ct_sns_gid_pt_data * gid_data ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2012-02-09 23:15:57 +04:00
uint16_t gid_pt_rsp_size ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_gid_pt ( vha , list ) ;
2005-04-17 02:20:36 +04:00
gid_data = NULL ;
2012-02-09 23:15:57 +04:00
gid_pt_rsp_size = qla2x00_gid_pt_rsp_size ( vha ) ;
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GID_PT_REQ_SIZE ;
arg . rsp_size = gid_pt_rsp_size ;
arg . nport_handle = NPH_SNS ;
2005-04-17 02:20:36 +04:00
/* Issue GID_PT */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GID_PT_CMD , gid_pt_rsp_size ) ;
2005-04-17 02:20:36 +04:00
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_type */
ct_req - > req . gid_pt . port_type = NS_NX_PORT_TYPE ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-04-17 02:20:36 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2055 ,
" GID_PT issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " GID_PT " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Set port IDs in switch info list. */
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
gid_data = & ct_rsp - > rsp . gid_pt . entries [ i ] ;
list [ i ] . d_id . b . domain = gid_data - > port_id [ 0 ] ;
list [ i ] . d_id . b . area = gid_data - > port_id [ 1 ] ;
list [ i ] . d_id . b . al_pa = gid_data - > port_id [ 2 ] ;
2007-08-13 21:13:18 +04:00
memset ( list [ i ] . fabric_port_name , 0 , WWN_SIZE ) ;
list [ i ] . fp_speed = PORT_SPEED_UNKNOWN ;
2005-04-17 02:20:36 +04:00
/* Last one exit. */
if ( gid_data - > control_byte & BIT_7 ) {
list [ i ] . d_id . b . rsvd_1 = gid_data - > control_byte ;
break ;
}
}
/*
* If we ' ve used all available slots , then the switch is
* reporting back more devices than we can handle with this
* single call . Return a failed status , and let GA_NXT handle
* the overload .
*/
2012-02-09 23:15:57 +04:00
if ( i = = ha - > max_fibre_devices )
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
}
return ( rval ) ;
}
/**
* qla2x00_gpn_id ( ) - SNS Get Port Name ( GPN_ID ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_gpn_id ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2005-04-17 02:20:36 +04:00
uint16_t i ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_gpn_id ( vha , list ) ;
2005-04-17 02:20:36 +04:00
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GPN_ID_REQ_SIZE ;
arg . rsp_size = GPN_ID_RSP_SIZE ;
arg . nport_handle = NPH_SNS ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
/* Issue GPN_ID */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GPN_ID_CMD ,
2005-04-17 02:20:36 +04:00
GPN_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id */
ct_req - > req . port_id . port_id [ 0 ] = list [ i ] . d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = list [ i ] . d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = list [ i ] . d_id . b . al_pa ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-04-17 02:20:36 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2056 ,
" GPN_ID issue IOCB failed (%d). \n " , rval ) ;
2012-02-09 23:16:00 +04:00
break ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp ,
2005-07-06 21:30:47 +04:00
" GPN_ID " ) ! = QLA_SUCCESS ) {
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
2012-02-09 23:16:00 +04:00
break ;
2005-04-17 02:20:36 +04:00
} else {
/* Save portname */
memcpy ( list [ i ] . port_name ,
ct_rsp - > rsp . gpn_id . port_name , WWN_SIZE ) ;
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
/**
* qla2x00_gnn_id ( ) - SNS Get Node Name ( GNN_ID ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_gnn_id ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2005-04-17 02:20:36 +04:00
uint16_t i ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_gnn_id ( vha , list ) ;
2005-04-17 02:20:36 +04:00
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GNN_ID_REQ_SIZE ;
arg . rsp_size = GNN_ID_RSP_SIZE ;
arg . nport_handle = NPH_SNS ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
/* Issue GNN_ID */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GNN_ID_CMD ,
2005-04-17 02:20:36 +04:00
GNN_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id */
ct_req - > req . port_id . port_id [ 0 ] = list [ i ] . d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = list [ i ] . d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = list [ i ] . d_id . b . al_pa ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-04-17 02:20:36 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2057 ,
" GNN_ID issue IOCB failed (%d). \n " , rval ) ;
2012-02-09 23:16:00 +04:00
break ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp ,
2005-07-06 21:30:47 +04:00
" GNN_ID " ) ! = QLA_SUCCESS ) {
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
2012-02-09 23:16:00 +04:00
break ;
2005-04-17 02:20:36 +04:00
} else {
/* Save nodename */
memcpy ( list [ i ] . node_name ,
ct_rsp - > rsp . gnn_id . node_name , WWN_SIZE ) ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2058 ,
2013-08-27 09:37:27 +04:00
" GID_PT entry - nn %8phN pn %8phN "
2005-04-17 02:20:36 +04:00
" portid=%02x%02x%02x. \n " ,
2013-08-27 09:37:27 +04:00
list [ i ] . node_name , list [ i ] . port_name ,
2005-04-17 02:20:36 +04:00
list [ i ] . d_id . b . domain , list [ i ] . d_id . b . area ,
2011-07-14 23:00:13 +04:00
list [ i ] . d_id . b . al_pa ) ;
2005-04-17 02:20:36 +04:00
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
2017-12-28 23:33:31 +03:00
static void qla2x00_async_sns_sp_done ( void * s , int rc )
{
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
struct ct_sns_pkt * ct_sns ;
struct qla_work_evt * e ;
sp - > rc = rc ;
if ( rc = = QLA_SUCCESS ) {
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s exiting normally. \n " ,
sp - > name ) ;
} else if ( rc = = QLA_FUNCTION_TIMEOUT ) {
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s timeout \n " , sp - > name ) ;
} else {
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
sp - > retry_count + + ;
if ( sp - > retry_count > 3 )
goto err ;
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s fail rc %x. Retry count %d \n " ,
sp - > name , rc , sp - > retry_count ) ;
e = qla2x00_alloc_work ( vha , QLA_EVT_SP_RETRY ) ;
if ( ! e )
goto err2 ;
del_timer ( & sp - > u . iocb_cmd . timer ) ;
e - > u . iosb . sp = sp ;
qla2x00_post_work ( vha , e ) ;
return ;
}
err :
e = qla2x00_alloc_work ( vha , QLA_EVT_UNMAP ) ;
err2 :
if ( ! e ) {
/* please ignore kernel warning. otherwise, we have mem leak. */
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
sp - > free ( sp ) ;
return ;
}
e - > u . iosb . sp = sp ;
qla2x00_post_work ( vha , e ) ;
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_rft_id ( ) - SNS Register FC - 4 TYPEs ( RFT_ID ) supported by the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_rft_id ( scsi_qla_host_t * vha )
2005-04-17 02:20:36 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_rft_id ( vha ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
return qla_async_rftid ( vha , & vha - > d_id ) ;
}
2017-01-20 09:28:00 +03:00
2017-12-28 23:33:31 +03:00
static int qla_async_rftid ( scsi_qla_host_t * vha , port_id_t * d_id )
{
int rval = QLA_MEMORY_ALLOC_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
struct ct_sns_pkt * ct_sns ;
if ( ! vha - > flags . online )
goto done ;
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " rft_id " ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
sp - > u . iocb_cmd . u . ctarg . req = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . req_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
ql_log ( ql_log_warn , vha , 0xd041 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . rsp = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . rsp_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xd042 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2017-12-28 23:33:31 +03:00
ct_req = qla2x00_prep_ct_req ( ct_sns , RFT_ID_CMD , RFT_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT arguments -- port_id, FC-4 types */
2008-11-06 21:40:19 +03:00
ct_req - > req . rft_id . port_id [ 0 ] = vha - > d_id . b . domain ;
ct_req - > req . rft_id . port_id [ 1 ] = vha - > d_id . b . area ;
ct_req - > req . rft_id . port_id [ 2 ] = vha - > d_id . b . al_pa ;
2005-04-17 02:20:36 +04:00
ct_req - > req . rft_id . fc4_types [ 2 ] = 0x01 ; /* FCP-3 */
2017-06-21 23:48:44 +03:00
if ( vha - > flags . nvme_enabled )
ct_req - > req . rft_id . fc4_types [ 6 ] = 1 ; /* NVMe type 28h */
2017-12-28 23:33:31 +03:00
sp - > u . iocb_cmd . u . ctarg . req_size = RFT_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = RFT_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_sns_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2005-04-17 02:20:36 +04:00
if ( rval ! = QLA_SUCCESS ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2043 ,
" RFT_ID issue IOCB failed (%d). \n " , rval ) ;
2017-12-28 23:33:31 +03:00
goto done_free_sp ;
2005-04-17 02:20:36 +04:00
}
2017-12-28 23:33:31 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - hdl=%x portid %06x. \n " ,
sp - > name , sp - > handle , d_id - > b24 ) ;
return rval ;
done_free_sp :
sp - > free ( sp ) ;
done :
return rval ;
2005-04-17 02:20:36 +04:00
}
/**
* qla2x00_rff_id ( ) - SNS Register FC - 4 Features ( RFF_ID ) supported by the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
* @ type : not used
2005-04-17 02:20:36 +04:00
*
* Returns 0 on success .
*/
int
2017-06-21 23:48:44 +03:00
qla2x00_rff_id ( scsi_qla_host_t * vha , u8 type )
2005-04-17 02:20:36 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2046 ,
" RFF_ID call not supported on ISP2100/ISP2200. \n " ) ;
2005-04-17 02:20:36 +04:00
return ( QLA_SUCCESS ) ;
}
2017-12-28 23:33:31 +03:00
return qla_async_rffid ( vha , & vha - > d_id , qlt_rff_id ( vha ) ,
FC4_TYPE_FCP_SCSI ) ;
}
2017-01-20 09:28:00 +03:00
2017-12-28 23:33:31 +03:00
static int qla_async_rffid ( scsi_qla_host_t * vha , port_id_t * d_id ,
u8 fc4feature , u8 fc4type )
{
int rval = QLA_MEMORY_ALLOC_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
struct ct_sns_pkt * ct_sns ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " rff_id " ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
sp - > u . iocb_cmd . u . ctarg . req = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . req_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
ql_log ( ql_log_warn , vha , 0xd041 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
sp - > u . iocb_cmd . u . ctarg . rsp = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . rsp_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xd042 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
2012-05-15 22:34:28 +04:00
2017-12-28 23:33:31 +03:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( ct_sns , RFF_ID_CMD , RFF_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
ct_req - > req . rff_id . port_id [ 0 ] = d_id - > b . domain ;
ct_req - > req . rff_id . port_id [ 1 ] = d_id - > b . area ;
ct_req - > req . rff_id . port_id [ 2 ] = d_id - > b . al_pa ;
ct_req - > req . rff_id . fc4_feature = fc4feature ;
ct_req - > req . rff_id . fc4_type = fc4type ; /* SCSI - FCP */
sp - > u . iocb_cmd . u . ctarg . req_size = RFF_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = RFF_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_sns_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2005-04-17 02:20:36 +04:00
if ( rval ! = QLA_SUCCESS ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2047 ,
" RFF_ID issue IOCB failed (%d). \n " , rval ) ;
2017-12-28 23:33:31 +03:00
goto done_free_sp ;
2005-04-17 02:20:36 +04:00
}
2017-12-28 23:33:31 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - hdl=%x portid %06x feature %x type %x. \n " ,
sp - > name , sp - > handle , d_id - > b24 , fc4feature , fc4type ) ;
return rval ;
done_free_sp :
sp - > free ( sp ) ;
done :
return rval ;
2005-04-17 02:20:36 +04:00
}
/**
* qla2x00_rnn_id ( ) - SNS Register Node Name ( RNN_ID ) of the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_rnn_id ( scsi_qla_host_t * vha )
2005-04-17 02:20:36 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_rnn_id ( vha ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
return qla_async_rnnid ( vha , & vha - > d_id , vha - > node_name ) ;
}
2017-01-20 09:28:00 +03:00
2017-12-28 23:33:31 +03:00
static int qla_async_rnnid ( scsi_qla_host_t * vha , port_id_t * d_id ,
u8 * node_name )
{
int rval = QLA_MEMORY_ALLOC_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
struct ct_sns_pkt * ct_sns ;
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " rnid " ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
sp - > u . iocb_cmd . u . ctarg . req = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . req_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
ql_log ( ql_log_warn , vha , 0xd041 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . rsp = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . rsp_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xd042 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2017-12-28 23:33:31 +03:00
ct_req = qla2x00_prep_ct_req ( ct_sns , RNN_ID_CMD , RNN_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT arguments -- port_id, node_name */
2008-11-06 21:40:19 +03:00
ct_req - > req . rnn_id . port_id [ 0 ] = vha - > d_id . b . domain ;
ct_req - > req . rnn_id . port_id [ 1 ] = vha - > d_id . b . area ;
ct_req - > req . rnn_id . port_id [ 2 ] = vha - > d_id . b . al_pa ;
memcpy ( ct_req - > req . rnn_id . node_name , vha - > node_name , WWN_SIZE ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
sp - > u . iocb_cmd . u . ctarg . req_size = RNN_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = RNN_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_sns_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2005-04-17 02:20:36 +04:00
if ( rval ! = QLA_SUCCESS ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x204d ,
" RNN_ID issue IOCB failed (%d). \n " , rval ) ;
2017-12-28 23:33:31 +03:00
goto done_free_sp ;
2005-04-17 02:20:36 +04:00
}
2017-12-28 23:33:31 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - hdl=%x portid %06x \n " ,
sp - > name , sp - > handle , d_id - > b24 ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
return rval ;
done_free_sp :
sp - > free ( sp ) ;
done :
return rval ;
2005-04-17 02:20:36 +04:00
}
2006-10-02 23:00:44 +04:00
void
2014-09-25 13:16:46 +04:00
qla2x00_get_sym_node_name ( scsi_qla_host_t * vha , uint8_t * snn , size_t size )
2006-10-02 23:00:44 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2013-03-28 16:21:23 +04:00
if ( IS_QLAFX00 ( ha ) )
2014-09-25 13:16:46 +04:00
snprintf ( snn , size , " %s FW:v%s DVR:v%s " , ha - > model_number ,
2013-03-28 16:21:23 +04:00
ha - > mr . fw_version , qla2x00_version_str ) ;
else
2014-09-25 13:16:46 +04:00
snprintf ( snn , size ,
" %s FW:v%d.%02d.%02d DVR:v%s " , ha - > model_number ,
2013-03-28 16:21:23 +04:00
ha - > fw_major_version , ha - > fw_minor_version ,
ha - > fw_subminor_version , qla2x00_version_str ) ;
2006-10-02 23:00:44 +04:00
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_rsnn_nn ( ) - SNS Register Symbolic Node Name ( RSNN_NN ) of the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_rsnn_nn ( scsi_qla_host_t * vha )
2005-04-17 02:20:36 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2050 ,
" RSNN_ID call unsupported on ISP2100/ISP2200. \n " ) ;
2005-04-17 02:20:36 +04:00
return ( QLA_SUCCESS ) ;
}
2017-12-28 23:33:31 +03:00
return qla_async_rsnn_nn ( vha ) ;
}
2017-01-20 09:28:00 +03:00
2017-12-28 23:33:31 +03:00
static int qla_async_rsnn_nn ( scsi_qla_host_t * vha )
{
int rval = QLA_MEMORY_ALLOC_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
struct ct_sns_pkt * ct_sns ;
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " rsnn_nn " ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
sp - > u . iocb_cmd . u . ctarg . req = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . req_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
ql_log ( ql_log_warn , vha , 0xd041 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . rsp = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . rsp_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xd042 ,
" %s: Failed to allocate ct_sns request. \n " ,
__func__ ) ;
goto done_free_sp ;
}
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
2017-12-28 23:33:31 +03:00
ct_req = qla2x00_prep_ct_req ( ct_sns , RSNN_NN_CMD , RSNN_NN_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT arguments -- node_name, symbolic node_name, size */
2008-11-06 21:40:19 +03:00
memcpy ( ct_req - > req . rsnn_nn . node_name , vha - > node_name , WWN_SIZE ) ;
2005-07-06 21:32:07 +04:00
2005-04-17 02:20:36 +04:00
/* Prepare the Symbolic Node Name */
2014-09-25 13:16:46 +04:00
qla2x00_get_sym_node_name ( vha , ct_req - > req . rsnn_nn . sym_node_name ,
sizeof ( ct_req - > req . rsnn_nn . sym_node_name ) ) ;
2006-10-02 23:00:44 +04:00
ct_req - > req . rsnn_nn . name_len =
( uint8_t ) strlen ( ct_req - > req . rsnn_nn . sym_node_name ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
sp - > u . iocb_cmd . u . ctarg . req_size = 24 + 1 + ct_req - > req . rsnn_nn . name_len ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = RSNN_NN_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_sns_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2005-04-17 02:20:36 +04:00
if ( rval ! = QLA_SUCCESS ) {
2017-12-28 23:33:31 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2043 ,
" RFT_ID issue IOCB failed (%d). \n " , rval ) ;
goto done_free_sp ;
2005-04-17 02:20:36 +04:00
}
2017-12-28 23:33:31 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - hdl=%x. \n " ,
sp - > name , sp - > handle ) ;
2005-04-17 02:20:36 +04:00
2017-12-28 23:33:31 +03:00
return rval ;
done_free_sp :
sp - > free ( sp ) ;
done :
return rval ;
2005-04-17 02:20:36 +04:00
}
/**
* qla2x00_prep_sns_cmd ( ) - Prepare common SNS command request fields for query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ cmd : GS command
* @ scmd_len : Subcommand length
* @ data_size : response size in bytes
*
* Returns a pointer to the @ ha ' s sns_cmd .
*/
static inline struct sns_cmd_pkt *
2008-11-06 21:40:19 +03:00
qla2x00_prep_sns_cmd ( scsi_qla_host_t * vha , uint16_t cmd , uint16_t scmd_len ,
2005-04-17 02:20:36 +04:00
uint16_t data_size )
{
uint16_t wc ;
struct sns_cmd_pkt * sns_cmd ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
sns_cmd = ha - > sns_cmd ;
memset ( sns_cmd , 0 , sizeof ( struct sns_cmd_pkt ) ) ;
wc = data_size / 2 ; /* Size in 16bit words. */
sns_cmd - > p . cmd . buffer_length = cpu_to_le16 ( wc ) ;
sns_cmd - > p . cmd . buffer_address [ 0 ] = cpu_to_le32 ( LSD ( ha - > sns_cmd_dma ) ) ;
sns_cmd - > p . cmd . buffer_address [ 1 ] = cpu_to_le32 ( MSD ( ha - > sns_cmd_dma ) ) ;
sns_cmd - > p . cmd . subcommand_length = cpu_to_le16 ( scmd_len ) ;
sns_cmd - > p . cmd . subcommand = cpu_to_le16 ( cmd ) ;
wc = ( data_size - 16 ) / 4 ; /* Size in 32bit words. */
sns_cmd - > p . cmd . size = cpu_to_le16 ( wc ) ;
2013-08-27 09:37:40 +04:00
vha - > qla_stats . control_requests + + ;
2005-04-17 02:20:36 +04:00
return ( sns_cmd ) ;
}
/**
* qla2x00_sns_ga_nxt ( ) - SNS scan for fabric devices via GA_NXT command .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ fcport : fcport entry to updated
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_ga_nxt ( scsi_qla_host_t * vha , fc_port_t * fcport )
2005-04-17 02:20:36 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
struct sns_cmd_pkt * sns_cmd ;
/* Issue GA_NXT. */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , GA_NXT_CMD , GA_NXT_SNS_SCMD_LEN ,
2005-04-17 02:20:36 +04:00
GA_NXT_SNS_DATA_SIZE ) ;
/* Prepare SNS command arguments -- port_id. */
sns_cmd - > p . cmd . param [ 0 ] = fcport - > d_id . b . al_pa ;
sns_cmd - > p . cmd . param [ 1 ] = fcport - > d_id . b . area ;
sns_cmd - > p . cmd . param [ 2 ] = fcport - > d_id . b . domain ;
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma , GA_NXT_SNS_CMD_SIZE / 2 ,
2005-04-17 02:20:36 +04:00
sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x205f ,
" GA_NXT Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . gan_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . gan_data [ 9 ] ! = 0x02 ) {
2011-11-18 21:03:07 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2084 ,
2011-07-14 23:00:13 +04:00
" GA_NXT failed, rejected request ga_nxt_rsp: \n " ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2074 ,
sns_cmd - > p . gan_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Populate fc_port_t entry. */
fcport - > d_id . b . domain = sns_cmd - > p . gan_data [ 17 ] ;
fcport - > d_id . b . area = sns_cmd - > p . gan_data [ 18 ] ;
fcport - > d_id . b . al_pa = sns_cmd - > p . gan_data [ 19 ] ;
memcpy ( fcport - > node_name , & sns_cmd - > p . gan_data [ 284 ] , WWN_SIZE ) ;
memcpy ( fcport - > port_name , & sns_cmd - > p . gan_data [ 20 ] , WWN_SIZE ) ;
if ( sns_cmd - > p . gan_data [ 16 ] ! = NS_N_PORT_TYPE & &
sns_cmd - > p . gan_data [ 16 ] ! = NS_NL_PORT_TYPE )
fcport - > d_id . b . domain = 0xf0 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2061 ,
2013-08-27 09:37:27 +04:00
" GA_NXT entry - nn %8phN pn %8phN "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2013-08-27 09:37:27 +04:00
fcport - > node_name , fcport - > port_name ,
2005-04-17 02:20:36 +04:00
fcport - > d_id . b . domain , fcport - > d_id . b . area ,
2011-07-14 23:00:13 +04:00
fcport - > d_id . b . al_pa ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
/**
* qla2x00_sns_gid_pt ( ) - SNS scan for fabric devices via GID_PT command .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* NOTE : Non - Nx_Ports are not requested .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_gid_pt ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
int rval ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
uint16_t i ;
uint8_t * entry ;
struct sns_cmd_pkt * sns_cmd ;
2012-02-09 23:15:57 +04:00
uint16_t gid_pt_sns_data_size ;
gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size ( vha ) ;
2005-04-17 02:20:36 +04:00
/* Issue GID_PT. */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , GID_PT_CMD , GID_PT_SNS_SCMD_LEN ,
2012-02-09 23:15:57 +04:00
gid_pt_sns_data_size ) ;
2005-04-17 02:20:36 +04:00
/* Prepare SNS command arguments -- port_type. */
sns_cmd - > p . cmd . param [ 0 ] = NS_NX_PORT_TYPE ;
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma , GID_PT_SNS_CMD_SIZE / 2 ,
2005-04-17 02:20:36 +04:00
sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x206d ,
" GID_PT Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . gid_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . gid_data [ 9 ] ! = 0x02 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202f ,
" GID_PT failed, rejected request, gid_rsp: \n " ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2081 ,
sns_cmd - > p . gid_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Set port IDs in switch info list. */
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
entry = & sns_cmd - > p . gid_data [ ( i * 4 ) + 16 ] ;
list [ i ] . d_id . b . domain = entry [ 1 ] ;
list [ i ] . d_id . b . area = entry [ 2 ] ;
list [ i ] . d_id . b . al_pa = entry [ 3 ] ;
/* Last one exit. */
if ( entry [ 0 ] & BIT_7 ) {
list [ i ] . d_id . b . rsvd_1 = entry [ 0 ] ;
break ;
}
}
/*
* If we ' ve used all available slots , then the switch is
* reporting back more devices that we can handle with this
* single call . Return a failed status , and let GA_NXT handle
* the overload .
*/
2012-02-09 23:15:57 +04:00
if ( i = = ha - > max_fibre_devices )
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
}
return ( rval ) ;
}
/**
* qla2x00_sns_gpn_id ( ) - SNS Get Port Name ( GPN_ID ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_gpn_id ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
uint16_t i ;
struct sns_cmd_pkt * sns_cmd ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
/* Issue GPN_ID */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , GPN_ID_CMD ,
2005-04-17 02:20:36 +04:00
GPN_ID_SNS_SCMD_LEN , GPN_ID_SNS_DATA_SIZE ) ;
/* Prepare SNS command arguments -- port_id. */
sns_cmd - > p . cmd . param [ 0 ] = list [ i ] . d_id . b . al_pa ;
sns_cmd - > p . cmd . param [ 1 ] = list [ i ] . d_id . b . area ;
sns_cmd - > p . cmd . param [ 2 ] = list [ i ] . d_id . b . domain ;
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma ,
2005-04-17 02:20:36 +04:00
GPN_ID_SNS_CMD_SIZE / 2 , sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2032 ,
" GPN_ID Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . gpn_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . gpn_data [ 9 ] ! = 0x02 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x207e ,
" GPN_ID failed, rejected request, gpn_rsp: \n " ) ;
2013-03-28 16:21:23 +04:00
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x207f ,
2011-07-14 23:00:13 +04:00
sns_cmd - > p . gpn_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Save portname */
memcpy ( list [ i ] . port_name , & sns_cmd - > p . gpn_data [ 16 ] ,
WWN_SIZE ) ;
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
/**
* qla2x00_sns_gnn_id ( ) - SNS Get Node Name ( GNN_ID ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
* @ list : switch info entries to populate
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_gnn_id ( scsi_qla_host_t * vha , sw_info_t * list )
2005-04-17 02:20:36 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
uint16_t i ;
struct sns_cmd_pkt * sns_cmd ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2005-04-17 02:20:36 +04:00
/* Issue GNN_ID */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , GNN_ID_CMD ,
2005-04-17 02:20:36 +04:00
GNN_ID_SNS_SCMD_LEN , GNN_ID_SNS_DATA_SIZE ) ;
/* Prepare SNS command arguments -- port_id. */
sns_cmd - > p . cmd . param [ 0 ] = list [ i ] . d_id . b . al_pa ;
sns_cmd - > p . cmd . param [ 1 ] = list [ i ] . d_id . b . area ;
sns_cmd - > p . cmd . param [ 2 ] = list [ i ] . d_id . b . domain ;
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma ,
2005-04-17 02:20:36 +04:00
GNN_ID_SNS_CMD_SIZE / 2 , sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203f ,
" GNN_ID Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . gnn_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . gnn_data [ 9 ] ! = 0x02 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2082 ,
" GNN_ID failed, rejected request, gnn_rsp: \n " ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x207a ,
sns_cmd - > p . gnn_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
/* Save nodename */
memcpy ( list [ i ] . node_name , & sns_cmd - > p . gnn_data [ 16 ] ,
WWN_SIZE ) ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x206e ,
2013-08-27 09:37:27 +04:00
" GID_PT entry - nn %8phN pn %8phN "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2013-08-27 09:37:27 +04:00
list [ i ] . node_name , list [ i ] . port_name ,
2005-04-17 02:20:36 +04:00
list [ i ] . d_id . b . domain , list [ i ] . d_id . b . area ,
2011-07-14 23:00:13 +04:00
list [ i ] . d_id . b . al_pa ) ;
2005-04-17 02:20:36 +04:00
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
/**
* qla2x00_snd_rft_id ( ) - SNS Register FC - 4 TYPEs ( RFT_ID ) supported by the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_rft_id ( scsi_qla_host_t * vha )
2005-04-17 02:20:36 +04:00
{
int rval ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
struct sns_cmd_pkt * sns_cmd ;
/* Issue RFT_ID. */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , RFT_ID_CMD , RFT_ID_SNS_SCMD_LEN ,
2005-04-17 02:20:36 +04:00
RFT_ID_SNS_DATA_SIZE ) ;
/* Prepare SNS command arguments -- port_id, FC-4 types */
2008-11-06 21:40:19 +03:00
sns_cmd - > p . cmd . param [ 0 ] = vha - > d_id . b . al_pa ;
sns_cmd - > p . cmd . param [ 1 ] = vha - > d_id . b . area ;
sns_cmd - > p . cmd . param [ 2 ] = vha - > d_id . b . domain ;
2005-04-17 02:20:36 +04:00
sns_cmd - > p . cmd . param [ 5 ] = 0x01 ; /* FCP-3 */
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma , RFT_ID_SNS_CMD_SIZE / 2 ,
2005-04-17 02:20:36 +04:00
sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2060 ,
" RFT_ID Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . rft_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . rft_data [ 9 ] ! = 0x02 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2083 ,
" RFT_ID failed, rejected request rft_rsp: \n " ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2080 ,
sns_cmd - > p . rft_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2073 ,
" RFT_ID exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
/**
* qla2x00_sns_rnn_id ( ) - SNS Register Node Name ( RNN_ID ) of the HBA .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-04-17 02:20:36 +04:00
*
* This command uses the old Exectute SNS Command mailbox routine .
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_sns_rnn_id ( scsi_qla_host_t * vha )
2005-04-17 02:20:36 +04:00
{
int rval ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-04-17 02:20:36 +04:00
struct sns_cmd_pkt * sns_cmd ;
/* Issue RNN_ID. */
/* Prepare SNS command request. */
2008-11-06 21:40:19 +03:00
sns_cmd = qla2x00_prep_sns_cmd ( vha , RNN_ID_CMD , RNN_ID_SNS_SCMD_LEN ,
2005-04-17 02:20:36 +04:00
RNN_ID_SNS_DATA_SIZE ) ;
/* Prepare SNS command arguments -- port_id, nodename. */
2008-11-06 21:40:19 +03:00
sns_cmd - > p . cmd . param [ 0 ] = vha - > d_id . b . al_pa ;
sns_cmd - > p . cmd . param [ 1 ] = vha - > d_id . b . area ;
sns_cmd - > p . cmd . param [ 2 ] = vha - > d_id . b . domain ;
sns_cmd - > p . cmd . param [ 4 ] = vha - > node_name [ 7 ] ;
sns_cmd - > p . cmd . param [ 5 ] = vha - > node_name [ 6 ] ;
sns_cmd - > p . cmd . param [ 6 ] = vha - > node_name [ 5 ] ;
sns_cmd - > p . cmd . param [ 7 ] = vha - > node_name [ 4 ] ;
sns_cmd - > p . cmd . param [ 8 ] = vha - > node_name [ 3 ] ;
sns_cmd - > p . cmd . param [ 9 ] = vha - > node_name [ 2 ] ;
sns_cmd - > p . cmd . param [ 10 ] = vha - > node_name [ 1 ] ;
sns_cmd - > p . cmd . param [ 11 ] = vha - > node_name [ 0 ] ;
2005-04-17 02:20:36 +04:00
/* Execute SNS command. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_send_sns ( vha , ha - > sns_cmd_dma , RNN_ID_SNS_CMD_SIZE / 2 ,
2005-04-17 02:20:36 +04:00
sizeof ( struct sns_cmd_pkt ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x204a ,
" RNN_ID Send SNS failed (%d). \n " , rval ) ;
2005-04-17 02:20:36 +04:00
} else if ( sns_cmd - > p . rnn_data [ 8 ] ! = 0x80 | |
sns_cmd - > p . rnn_data [ 9 ] ! = 0x02 ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x207b ,
" RNN_ID failed, rejected request, rnn_rsp: \n " ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x207c ,
sns_cmd - > p . rnn_data , 16 ) ;
2005-04-17 02:20:36 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x204c ,
" RNN_ID exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
2005-08-27 06:08:30 +04:00
/**
2008-02-03 18:28:22 +03:00
* qla2x00_mgmt_svr_login ( ) - Login to fabric Management Service .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
*
* Returns 0 on success .
*/
2017-01-20 09:28:00 +03:00
int
2008-11-06 21:40:19 +03:00
qla2x00_mgmt_svr_login ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
2012-02-09 23:15:42 +04:00
int ret , rval ;
2005-08-27 06:08:30 +04:00
uint16_t mb [ MAILBOX_REGISTER_COUNT ] ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ret = QLA_SUCCESS ;
2008-11-06 21:40:19 +03:00
if ( vha - > flags . management_server_logged_in )
2005-08-27 06:08:30 +04:00
return ret ;
2012-02-09 23:15:42 +04:00
rval = ha - > isp_ops - > fabric_login ( vha , vha - > mgmt_svr_loop_id , 0xff , 0xff ,
2012-08-22 22:21:18 +04:00
0xfa , mb , BIT_1 ) ;
2012-02-09 23:15:42 +04:00
if ( rval ! = QLA_SUCCESS | | mb [ 0 ] ! = MBS_COMMAND_COMPLETE ) {
if ( rval = = QLA_MEMORY_ALLOC_FAILED )
ql_dbg ( ql_dbg_disc , vha , 0x2085 ,
" Failed management_server login: loopid=%x "
" rval=%d \n " , vha - > mgmt_svr_loop_id , rval ) ;
else
ql_dbg ( ql_dbg_disc , vha , 0x2024 ,
" Failed management_server login: loopid=%x "
" mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x. \n " ,
vha - > mgmt_svr_loop_id , mb [ 0 ] , mb [ 1 ] , mb [ 2 ] , mb [ 6 ] ,
mb [ 7 ] ) ;
2005-08-27 06:08:30 +04:00
ret = QLA_FUNCTION_FAILED ;
} else
2008-11-06 21:40:19 +03:00
vha - > flags . management_server_logged_in = 1 ;
2005-08-27 06:08:30 +04:00
return ret ;
}
/**
* qla2x00_prep_ms_fdmi_iocb ( ) - Prepare common MS IOCB fields for FDMI query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
* @ req_size : request size in bytes
* @ rsp_size : response size in bytes
*
* Returns a pointer to the @ ha ' s ms_iocb .
*/
void *
2008-11-06 21:40:19 +03:00
qla2x00_prep_ms_fdmi_iocb ( scsi_qla_host_t * vha , uint32_t req_size ,
2005-08-27 06:08:30 +04:00
uint32_t rsp_size )
{
ms_iocb_entry_t * ms_pkt ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ms_pkt = ha - > ms_iocb ;
memset ( ms_pkt , 0 , sizeof ( ms_iocb_entry_t ) ) ;
ms_pkt - > entry_type = MS_IOCB_TYPE ;
ms_pkt - > entry_count = 1 ;
2008-11-06 21:40:19 +03:00
SET_TARGET_ID ( ha , ms_pkt - > loop_id , vha - > mgmt_svr_loop_id ) ;
2015-07-09 17:24:08 +03:00
ms_pkt - > control_flags = cpu_to_le16 ( CF_READ | CF_HEAD_TAG ) ;
2008-02-29 01:06:11 +03:00
ms_pkt - > timeout = cpu_to_le16 ( ha - > r_a_tov / 10 * 2 ) ;
2015-07-09 17:24:08 +03:00
ms_pkt - > cmd_dsd_count = cpu_to_le16 ( 1 ) ;
ms_pkt - > total_dsd_count = cpu_to_le16 ( 2 ) ;
2005-08-27 06:08:30 +04:00
ms_pkt - > rsp_bytecount = cpu_to_le32 ( rsp_size ) ;
ms_pkt - > req_bytecount = cpu_to_le32 ( req_size ) ;
ms_pkt - > dseg_req_address [ 0 ] = cpu_to_le32 ( LSD ( ha - > ct_sns_dma ) ) ;
ms_pkt - > dseg_req_address [ 1 ] = cpu_to_le32 ( MSD ( ha - > ct_sns_dma ) ) ;
ms_pkt - > dseg_req_length = ms_pkt - > req_bytecount ;
ms_pkt - > dseg_rsp_address [ 0 ] = cpu_to_le32 ( LSD ( ha - > ct_sns_dma ) ) ;
ms_pkt - > dseg_rsp_address [ 1 ] = cpu_to_le32 ( MSD ( ha - > ct_sns_dma ) ) ;
ms_pkt - > dseg_rsp_length = ms_pkt - > rsp_bytecount ;
return ms_pkt ;
}
/**
* qla24xx_prep_ms_fdmi_iocb ( ) - Prepare common MS IOCB fields for FDMI query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
* @ req_size : request size in bytes
* @ rsp_size : response size in bytes
*
* Returns a pointer to the @ ha ' s ms_iocb .
*/
void *
2008-11-06 21:40:19 +03:00
qla24xx_prep_ms_fdmi_iocb ( scsi_qla_host_t * vha , uint32_t req_size ,
2005-08-27 06:08:30 +04:00
uint32_t rsp_size )
{
struct ct_entry_24xx * ct_pkt ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ct_pkt = ( struct ct_entry_24xx * ) ha - > ms_iocb ;
memset ( ct_pkt , 0 , sizeof ( struct ct_entry_24xx ) ) ;
ct_pkt - > entry_type = CT_IOCB_TYPE ;
ct_pkt - > entry_count = 1 ;
2008-11-06 21:40:19 +03:00
ct_pkt - > nport_handle = cpu_to_le16 ( vha - > mgmt_svr_loop_id ) ;
2008-02-29 01:06:11 +03:00
ct_pkt - > timeout = cpu_to_le16 ( ha - > r_a_tov / 10 * 2 ) ;
2015-07-09 17:24:08 +03:00
ct_pkt - > cmd_dsd_count = cpu_to_le16 ( 1 ) ;
ct_pkt - > rsp_dsd_count = cpu_to_le16 ( 1 ) ;
2005-08-27 06:08:30 +04:00
ct_pkt - > rsp_byte_count = cpu_to_le32 ( rsp_size ) ;
ct_pkt - > cmd_byte_count = cpu_to_le32 ( req_size ) ;
ct_pkt - > dseg_0_address [ 0 ] = cpu_to_le32 ( LSD ( ha - > ct_sns_dma ) ) ;
ct_pkt - > dseg_0_address [ 1 ] = cpu_to_le32 ( MSD ( ha - > ct_sns_dma ) ) ;
ct_pkt - > dseg_0_len = ct_pkt - > cmd_byte_count ;
ct_pkt - > dseg_1_address [ 0 ] = cpu_to_le32 ( LSD ( ha - > ct_sns_dma ) ) ;
ct_pkt - > dseg_1_address [ 1 ] = cpu_to_le32 ( MSD ( ha - > ct_sns_dma ) ) ;
ct_pkt - > dseg_1_len = ct_pkt - > rsp_byte_count ;
2008-11-06 21:40:19 +03:00
ct_pkt - > vp_index = vha - > vp_idx ;
2005-08-27 06:08:30 +04:00
return ct_pkt ;
}
static inline ms_iocb_entry_t *
2008-11-06 21:40:19 +03:00
qla2x00_update_ms_fdmi_iocb ( scsi_qla_host_t * vha , uint32_t req_size )
2005-08-27 06:08:30 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ms_iocb_entry_t * ms_pkt = ha - > ms_iocb ;
struct ct_entry_24xx * ct_pkt = ( struct ct_entry_24xx * ) ha - > ms_iocb ;
2007-07-20 02:05:56 +04:00
if ( IS_FWI2_CAPABLE ( ha ) ) {
2005-08-27 06:08:30 +04:00
ct_pkt - > cmd_byte_count = cpu_to_le32 ( req_size ) ;
ct_pkt - > dseg_0_len = ct_pkt - > cmd_byte_count ;
} else {
ms_pkt - > req_bytecount = cpu_to_le32 ( req_size ) ;
ms_pkt - > dseg_req_length = ms_pkt - > req_bytecount ;
}
return ms_pkt ;
}
/**
* qla2x00_prep_ct_req ( ) - Prepare common CT request fields for SNS query .
2018-01-24 03:33:51 +03:00
* @ p : CT request buffer
2005-08-27 06:08:30 +04:00
* @ cmd : GS command
* @ rsp_size : response size in bytes
*
* Returns a pointer to the intitialized @ ct_req .
*/
static inline struct ct_sns_req *
2013-06-25 19:27:28 +04:00
qla2x00_prep_ct_fdmi_req ( struct ct_sns_pkt * p , uint16_t cmd ,
2005-08-27 06:08:30 +04:00
uint16_t rsp_size )
{
2013-06-25 19:27:28 +04:00
memset ( p , 0 , sizeof ( struct ct_sns_pkt ) ) ;
2005-08-27 06:08:30 +04:00
2013-06-25 19:27:28 +04:00
p - > p . req . header . revision = 0x01 ;
p - > p . req . header . gs_type = 0xFA ;
p - > p . req . header . gs_subtype = 0x10 ;
p - > p . req . command = cpu_to_be16 ( cmd ) ;
p - > p . req . max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
2005-08-27 06:08:30 +04:00
2013-06-25 19:27:28 +04:00
return & p - > p . req ;
2005-08-27 06:08:30 +04:00
}
/**
2018-01-24 03:33:51 +03:00
* qla2x00_fdmi_rhba ( ) - perform RHBA FDMI registration
* @ vha : HA context
2005-08-27 06:08:30 +04:00
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_fdmi_rhba ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
int rval , alen ;
uint32_t size , sn ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2014-09-25 13:16:46 +04:00
void * entries ;
2005-08-27 06:08:30 +04:00
struct ct_fdmi_hba_attr * eiter ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
/* Issue RHBA */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_fdmi_iocb ( vha , 0 , RHBA_RSP_SIZE ) ;
2005-08-27 06:08:30 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_fdmi_req ( ha - > ct_sns , RHBA_CMD , RHBA_RSP_SIZE ) ;
2005-08-27 06:08:30 +04:00
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare FDMI command arguments -- attribute block, attributes. */
2008-11-06 21:40:19 +03:00
memcpy ( ct_req - > req . rhba . hba_identifier , vha - > port_name , WWN_SIZE ) ;
2015-07-09 17:24:08 +03:00
ct_req - > req . rhba . entry_count = cpu_to_be32 ( 1 ) ;
2008-11-06 21:40:19 +03:00
memcpy ( ct_req - > req . rhba . port_name , vha - > port_name , WWN_SIZE ) ;
2005-08-27 06:08:30 +04:00
size = 2 * WWN_SIZE + 4 + 4 ;
/* Attributes */
ct_req - > req . rhba . attrs . count =
2015-07-09 17:24:08 +03:00
cpu_to_be32 ( FDMI_HBA_ATTR_COUNT ) ;
2005-08-27 06:08:30 +04:00
entries = ct_req - > req . rhba . hba_identifier ;
/* Nodename. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_NODE_NAME ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
2008-11-06 21:40:19 +03:00
memcpy ( eiter - > a . node_name , vha - > node_name , WWN_SIZE ) ;
2005-08-27 06:08:30 +04:00
size + = 4 + WWN_SIZE ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2025 ,
2013-08-27 09:37:27 +04:00
" NodeName = %8phN. \n " , eiter - > a . node_name ) ;
2005-08-27 06:08:30 +04:00
/* Manufacturer. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_MANUFACTURER ) ;
2013-02-08 10:57:55 +04:00
alen = strlen ( QLA2XXX_MANUFACTURER ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . manufacturer , sizeof ( eiter - > a . manufacturer ) ,
" %s " , " QLogic Corporation " ) ;
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2026 ,
" Manufacturer = %s. \n " , eiter - > a . manufacturer ) ;
2005-08-27 06:08:30 +04:00
/* Serial number. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_SERIAL_NUMBER ) ;
2014-09-25 13:16:46 +04:00
if ( IS_FWI2_CAPABLE ( ha ) )
qla2xxx_get_vpd_field ( vha , " SN " , eiter - > a . serial_num ,
sizeof ( eiter - > a . serial_num ) ) ;
else {
sn = ( ( ha - > serial0 & 0x1f ) < < 16 ) |
( ha - > serial2 < < 8 ) | ha - > serial1 ;
snprintf ( eiter - > a . serial_num , sizeof ( eiter - > a . serial_num ) ,
" %c%05d " , ' A ' + sn / 100000 , sn % 100000 ) ;
}
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . serial_num ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2027 ,
" Serial no. = %s. \n " , eiter - > a . serial_num ) ;
2005-08-27 06:08:30 +04:00
/* Model name. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_MODEL ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . model , sizeof ( eiter - > a . model ) ,
" %s " , ha - > model_number ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . model ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2028 ,
" Model Name = %s. \n " , eiter - > a . model ) ;
2005-08-27 06:08:30 +04:00
/* Model description. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_MODEL_DESCRIPTION ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . model_desc , sizeof ( eiter - > a . model_desc ) ,
" %s " , ha - > model_desc ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . model_desc ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2029 ,
" Model Desc = %s. \n " , eiter - > a . model_desc ) ;
2005-08-27 06:08:30 +04:00
/* Hardware version. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_HARDWARE_VERSION ) ;
2014-09-25 13:16:46 +04:00
if ( ! IS_FWI2_CAPABLE ( ha ) ) {
snprintf ( eiter - > a . hw_version , sizeof ( eiter - > a . hw_version ) ,
" HW:%s " , ha - > adapter_id ) ;
} else if ( qla2xxx_get_vpd_field ( vha , " MN " , eiter - > a . hw_version ,
sizeof ( eiter - > a . hw_version ) ) ) {
;
} else if ( qla2xxx_get_vpd_field ( vha , " EC " , eiter - > a . hw_version ,
sizeof ( eiter - > a . hw_version ) ) ) {
;
} else {
snprintf ( eiter - > a . hw_version , sizeof ( eiter - > a . hw_version ) ,
" HW:%s " , ha - > adapter_id ) ;
}
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . hw_version ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202a ,
" Hardware ver = %s. \n " , eiter - > a . hw_version ) ;
2005-08-27 06:08:30 +04:00
/* Driver version. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_DRIVER_VERSION ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . driver_version , sizeof ( eiter - > a . driver_version ) ,
" %s " , qla2x00_version_str ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . driver_version ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202b ,
" Driver ver = %s. \n " , eiter - > a . driver_version ) ;
2005-08-27 06:08:30 +04:00
/* Option ROM version. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_OPTION_ROM_VERSION ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . orom_version , sizeof ( eiter - > a . orom_version ) ,
" %d.%02d " , ha - > bios_revision [ 1 ] , ha - > bios_revision [ 0 ] ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . orom_version ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202c ,
" Optrom vers = %s. \n " , eiter - > a . orom_version ) ;
2005-08-27 06:08:30 +04:00
/* Firmware version */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
2015-07-09 17:24:08 +03:00
eiter - > type = cpu_to_be16 ( FDMI_HBA_FIRMWARE_VERSION ) ;
2014-09-25 13:16:46 +04:00
ha - > isp_ops - > fw_version_str ( vha , eiter - > a . fw_version ,
sizeof ( eiter - > a . fw_version ) ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . fw_version ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202d ,
" Firmware vers = %s. \n " , eiter - > a . fw_version ) ;
2005-08-27 06:08:30 +04:00
/* Update MS request size. */
2008-11-06 21:40:19 +03:00
qla2x00_update_ms_fdmi_iocb ( vha , size + 16 ) ;
2005-08-27 06:08:30 +04:00
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x202e ,
2013-08-27 09:37:27 +04:00
" RHBA identifier = %8phN size=%d. \n " ,
ct_req - > req . rhba . hba_identifier , size ) ;
2011-07-14 23:00:13 +04:00
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2076 ,
entries , size ) ;
2005-08-27 06:08:30 +04:00
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-08-27 06:08:30 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2030 ,
" RHBA issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " RHBA " ) ! =
2005-08-27 06:08:30 +04:00
QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
if ( ct_rsp - > header . reason_code = = CT_REASON_CANNOT_PERFORM & &
ct_rsp - > header . explanation_code = =
CT_EXPL_ALREADY_REGISTERED ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2034 ,
" HBA already registered. \n " ) ;
2005-08-27 06:08:30 +04:00
rval = QLA_ALREADY_REGISTERED ;
2014-09-25 13:16:46 +04:00
} else {
ql_dbg ( ql_dbg_disc , vha , 0x20ad ,
" RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x \n " ,
ct_rsp - > header . reason_code ,
ct_rsp - > header . explanation_code ) ;
2005-08-27 06:08:30 +04:00
}
} else {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2035 ,
" RHBA exiting normally. \n " ) ;
2005-08-27 06:08:30 +04:00
}
return rval ;
}
2014-09-25 13:16:46 +04:00
/**
2018-01-24 03:33:51 +03:00
* qla2x00_fdmi_rpa ( ) - perform RPA registration
* @ vha : HA context
2014-09-25 13:16:46 +04:00
*
* Returns 0 on success .
*/
static int
qla2x00_fdmi_rpa ( scsi_qla_host_t * vha )
{
int rval , alen ;
uint32_t size ;
struct qla_hw_data * ha = vha - > hw ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
void * entries ;
struct ct_fdmi_port_attr * eiter ;
struct init_cb_24xx * icb24 = ( struct init_cb_24xx * ) ha - > init_cb ;
struct new_utsname * p_sysid = NULL ;
/* Issue RPA */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
ms_pkt = ha - > isp_ops - > prep_ms_fdmi_iocb ( vha , 0 , RPA_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_fdmi_req ( ha - > ct_sns , RPA_CMD ,
RPA_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare FDMI command arguments -- attribute block, attributes. */
memcpy ( ct_req - > req . rpa . port_name , vha - > port_name , WWN_SIZE ) ;
size = WWN_SIZE + 4 ;
/* Attributes */
ct_req - > req . rpa . attrs . count = cpu_to_be32 ( FDMI_PORT_ATTR_COUNT ) ;
entries = ct_req - > req . rpa . port_name ;
/* FC4 types. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_FC4_TYPES ) ;
eiter - > len = cpu_to_be16 ( 4 + 32 ) ;
eiter - > a . fc4_types [ 2 ] = 0x01 ;
size + = 4 + 32 ;
ql_dbg ( ql_dbg_disc , vha , 0x2039 ,
" FC4_TYPES=%02x %02x. \n " ,
eiter - > a . fc4_types [ 2 ] ,
eiter - > a . fc4_types [ 1 ] ) ;
/* Supported speed. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_SUPPORT_SPEED ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
if ( IS_CNA_CAPABLE ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_10GB ) ;
else if ( IS_QLA27XX ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_32GB |
FDMI_PORT_SPEED_16GB |
FDMI_PORT_SPEED_8GB ) ;
else if ( IS_QLA2031 ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_16GB |
FDMI_PORT_SPEED_8GB |
FDMI_PORT_SPEED_4GB ) ;
else if ( IS_QLA25XX ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_8GB |
FDMI_PORT_SPEED_4GB |
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
else if ( IS_QLA24XX_TYPE ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_4GB |
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
else if ( IS_QLA23XX ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
else
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_1GB ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x203a ,
" Supported_Speed=%x. \n " , eiter - > a . sup_speed ) ;
/* Current speed. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_CURRENT_SPEED ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
switch ( ha - > link_data_rate ) {
case PORT_SPEED_1GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_1GB ) ;
break ;
case PORT_SPEED_2GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_2GB ) ;
break ;
case PORT_SPEED_4GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_4GB ) ;
break ;
case PORT_SPEED_8GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_8GB ) ;
break ;
case PORT_SPEED_10GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_10GB ) ;
break ;
case PORT_SPEED_16GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_16GB ) ;
break ;
case PORT_SPEED_32GB :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_32GB ) ;
break ;
default :
eiter - > a . cur_speed =
cpu_to_be32 ( FDMI_PORT_SPEED_UNKNOWN ) ;
break ;
}
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x203b ,
" Current_Speed=%x. \n " , eiter - > a . cur_speed ) ;
/* Max frame size. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_MAX_FRAME_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
eiter - > a . max_frame_size = IS_FWI2_CAPABLE ( ha ) ?
le16_to_cpu ( icb24 - > frame_payload_size ) :
le16_to_cpu ( ha - > init_cb - > frame_payload_size ) ;
eiter - > a . max_frame_size = cpu_to_be32 ( eiter - > a . max_frame_size ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x203c ,
" Max_Frame_Size=%x. \n " , eiter - > a . max_frame_size ) ;
/* OS device name. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_OS_DEVICE_NAME ) ;
snprintf ( eiter - > a . os_dev_name , sizeof ( eiter - > a . os_dev_name ) ,
" %s:host%lu " , QLA2XXX_DRIVER_NAME , vha - > host_no ) ;
alen = strlen ( eiter - > a . os_dev_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x204b ,
" OS_Device_Name=%s. \n " , eiter - > a . os_dev_name ) ;
/* Hostname. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_HOST_NAME ) ;
p_sysid = utsname ( ) ;
if ( p_sysid ) {
snprintf ( eiter - > a . host_name , sizeof ( eiter - > a . host_name ) ,
" %s " , p_sysid - > nodename ) ;
} else {
snprintf ( eiter - > a . host_name , sizeof ( eiter - > a . host_name ) ,
" %s " , fc_host_system_hostname ( vha - > host ) ) ;
}
alen = strlen ( eiter - > a . host_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x203d , " HostName=%s. \n " , eiter - > a . host_name ) ;
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb ( vha , size + 16 ) ;
ql_dbg ( ql_dbg_disc , vha , 0x203e ,
" RPA portname %016llx, size = %d. \n " ,
wwn_to_u64 ( ct_req - > req . rpa . port_name ) , size ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2079 ,
entries , size ) ;
/* Execute MS IOCB */
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
ql_dbg ( ql_dbg_disc , vha , 0x2040 ,
" RPA issue IOCB failed (%d). \n " , rval ) ;
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " RPA " ) ! =
QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
if ( ct_rsp - > header . reason_code = = CT_REASON_CANNOT_PERFORM & &
ct_rsp - > header . explanation_code = =
CT_EXPL_ALREADY_REGISTERED ) {
ql_dbg ( ql_dbg_disc , vha , 0x20cd ,
" RPA already registered. \n " ) ;
rval = QLA_ALREADY_REGISTERED ;
}
} else {
ql_dbg ( ql_dbg_disc , vha , 0x2041 ,
" RPA exiting normally. \n " ) ;
}
return rval ;
}
/**
2018-01-24 03:33:51 +03:00
* qla2x00_fdmiv2_rhba ( ) - perform RHBA FDMI v2 registration
* @ vha : HA context
2014-09-25 13:16:46 +04:00
*
* Returns 0 on success .
*/
static int
qla2x00_fdmiv2_rhba ( scsi_qla_host_t * vha )
{
int rval , alen ;
uint32_t size , sn ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
void * entries ;
struct ct_fdmiv2_hba_attr * eiter ;
struct qla_hw_data * ha = vha - > hw ;
struct init_cb_24xx * icb24 = ( struct init_cb_24xx * ) ha - > init_cb ;
struct new_utsname * p_sysid = NULL ;
/* Issue RHBA */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
ms_pkt = ha - > isp_ops - > prep_ms_fdmi_iocb ( vha , 0 , RHBA_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_fdmi_req ( ha - > ct_sns , RHBA_CMD ,
RHBA_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare FDMI command arguments -- attribute block, attributes. */
memcpy ( ct_req - > req . rhba2 . hba_identifier , vha - > port_name , WWN_SIZE ) ;
ct_req - > req . rhba2 . entry_count = cpu_to_be32 ( 1 ) ;
memcpy ( ct_req - > req . rhba2 . port_name , vha - > port_name , WWN_SIZE ) ;
size = 2 * WWN_SIZE + 4 + 4 ;
/* Attributes */
ct_req - > req . rhba2 . attrs . count = cpu_to_be32 ( FDMIV2_HBA_ATTR_COUNT ) ;
entries = ct_req - > req . rhba2 . hba_identifier ;
/* Nodename. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_NODE_NAME ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
memcpy ( eiter - > a . node_name , vha - > node_name , WWN_SIZE ) ;
size + = 4 + WWN_SIZE ;
ql_dbg ( ql_dbg_disc , vha , 0x207d ,
" NodeName = %016llx. \n " , wwn_to_u64 ( eiter - > a . node_name ) ) ;
/* Manufacturer. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_MANUFACTURER ) ;
snprintf ( eiter - > a . manufacturer , sizeof ( eiter - > a . manufacturer ) ,
" %s " , " QLogic Corporation " ) ;
eiter - > a . manufacturer [ strlen ( " QLogic Corporation " ) ] = ' \0 ' ;
alen = strlen ( eiter - > a . manufacturer ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20a5 ,
" Manufacturer = %s. \n " , eiter - > a . manufacturer ) ;
/* Serial number. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_SERIAL_NUMBER ) ;
if ( IS_FWI2_CAPABLE ( ha ) )
qla2xxx_get_vpd_field ( vha , " SN " , eiter - > a . serial_num ,
sizeof ( eiter - > a . serial_num ) ) ;
else {
sn = ( ( ha - > serial0 & 0x1f ) < < 16 ) |
( ha - > serial2 < < 8 ) | ha - > serial1 ;
snprintf ( eiter - > a . serial_num , sizeof ( eiter - > a . serial_num ) ,
" %c%05d " , ' A ' + sn / 100000 , sn % 100000 ) ;
}
alen = strlen ( eiter - > a . serial_num ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20a6 ,
" Serial no. = %s. \n " , eiter - > a . serial_num ) ;
/* Model name. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_MODEL ) ;
snprintf ( eiter - > a . model , sizeof ( eiter - > a . model ) ,
" %s " , ha - > model_number ) ;
alen = strlen ( eiter - > a . model ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20a7 ,
" Model Name = %s. \n " , eiter - > a . model ) ;
/* Model description. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_MODEL_DESCRIPTION ) ;
snprintf ( eiter - > a . model_desc , sizeof ( eiter - > a . model_desc ) ,
" %s " , ha - > model_desc ) ;
alen = strlen ( eiter - > a . model_desc ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20a8 ,
" Model Desc = %s. \n " , eiter - > a . model_desc ) ;
/* Hardware version. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_HARDWARE_VERSION ) ;
if ( ! IS_FWI2_CAPABLE ( ha ) ) {
snprintf ( eiter - > a . hw_version , sizeof ( eiter - > a . hw_version ) ,
" HW:%s " , ha - > adapter_id ) ;
} else if ( qla2xxx_get_vpd_field ( vha , " MN " , eiter - > a . hw_version ,
sizeof ( eiter - > a . hw_version ) ) ) {
;
} else if ( qla2xxx_get_vpd_field ( vha , " EC " , eiter - > a . hw_version ,
sizeof ( eiter - > a . hw_version ) ) ) {
;
} else {
snprintf ( eiter - > a . hw_version , sizeof ( eiter - > a . hw_version ) ,
" HW:%s " , ha - > adapter_id ) ;
}
alen = strlen ( eiter - > a . hw_version ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20a9 ,
" Hardware ver = %s. \n " , eiter - > a . hw_version ) ;
/* Driver version. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_DRIVER_VERSION ) ;
snprintf ( eiter - > a . driver_version , sizeof ( eiter - > a . driver_version ) ,
" %s " , qla2x00_version_str ) ;
alen = strlen ( eiter - > a . driver_version ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20aa ,
" Driver ver = %s. \n " , eiter - > a . driver_version ) ;
/* Option ROM version. */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_OPTION_ROM_VERSION ) ;
snprintf ( eiter - > a . orom_version , sizeof ( eiter - > a . orom_version ) ,
" %d.%02d " , ha - > bios_revision [ 1 ] , ha - > bios_revision [ 0 ] ) ;
alen = strlen ( eiter - > a . orom_version ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20ab ,
" Optrom version = %d.%02d. \n " , eiter - > a . orom_version [ 1 ] ,
eiter - > a . orom_version [ 0 ] ) ;
/* Firmware version */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_FIRMWARE_VERSION ) ;
ha - > isp_ops - > fw_version_str ( vha , eiter - > a . fw_version ,
sizeof ( eiter - > a . fw_version ) ) ;
alen = strlen ( eiter - > a . fw_version ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20ac ,
" Firmware vers = %s. \n " , eiter - > a . fw_version ) ;
/* OS Name and Version */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_OS_NAME_AND_VERSION ) ;
p_sysid = utsname ( ) ;
if ( p_sysid ) {
snprintf ( eiter - > a . os_version , sizeof ( eiter - > a . os_version ) ,
" %s %s %s " ,
p_sysid - > sysname , p_sysid - > release , p_sysid - > version ) ;
} else {
snprintf ( eiter - > a . os_version , sizeof ( eiter - > a . os_version ) ,
" %s %s " , " Linux " , fc_host_system_hostname ( vha - > host ) ) ;
}
alen = strlen ( eiter - > a . os_version ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20ae ,
" OS Name and Version = %s. \n " , eiter - > a . os_version ) ;
/* MAX CT Payload Length */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH ) ;
eiter - > a . max_ct_len = IS_FWI2_CAPABLE ( ha ) ?
le16_to_cpu ( icb24 - > frame_payload_size ) :
le16_to_cpu ( ha - > init_cb - > frame_payload_size ) ;
eiter - > a . max_ct_len = cpu_to_be32 ( eiter - > a . max_ct_len ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20af ,
" CT Payload Length = 0x%x. \n " , eiter - > a . max_ct_len ) ;
/* Node Sybolic Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_NODE_SYMBOLIC_NAME ) ;
qla2x00_get_sym_node_name ( vha , eiter - > a . sym_name ,
sizeof ( eiter - > a . sym_name ) ) ;
alen = strlen ( eiter - > a . sym_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20b0 ,
" Symbolic Name = %s. \n " , eiter - > a . sym_name ) ;
/* Vendor Id */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_VENDOR_ID ) ;
eiter - > a . vendor_id = cpu_to_be32 ( 0x1077 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20b1 ,
" Vendor Id = %x. \n " , eiter - > a . vendor_id ) ;
/* Num Ports */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_NUM_PORTS ) ;
eiter - > a . num_ports = cpu_to_be32 ( 1 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20b2 ,
" Port Num = %x. \n " , eiter - > a . num_ports ) ;
/* Fabric Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_FABRIC_NAME ) ;
memcpy ( eiter - > a . fabric_name , vha - > fabric_node_name , WWN_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
size + = 4 + WWN_SIZE ;
ql_dbg ( ql_dbg_disc , vha , 0x20b3 ,
" Fabric Name = %016llx. \n " , wwn_to_u64 ( eiter - > a . fabric_name ) ) ;
/* BIOS Version */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_BOOT_BIOS_NAME ) ;
snprintf ( eiter - > a . bios_name , sizeof ( eiter - > a . bios_name ) ,
" BIOS %d.%02d " , ha - > bios_revision [ 1 ] , ha - > bios_revision [ 0 ] ) ;
alen = strlen ( eiter - > a . bios_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20b4 ,
" BIOS Name = %s \n " , eiter - > a . bios_name ) ;
/* Vendor Identifier */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_HBA_TYPE_VENDOR_IDENTIFIER ) ;
2016-12-30 01:20:38 +03:00
snprintf ( eiter - > a . vendor_identifier , sizeof ( eiter - > a . vendor_identifier ) ,
2014-09-25 13:16:46 +04:00
" %s " , " QLGC " ) ;
2016-12-30 01:20:38 +03:00
alen = strlen ( eiter - > a . vendor_identifier ) ;
2014-09-25 13:16:46 +04:00
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201b ,
2016-12-30 01:20:38 +03:00
" Vendor Identifier = %s. \n " , eiter - > a . vendor_identifier ) ;
2014-09-25 13:16:46 +04:00
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb ( vha , size + 16 ) ;
ql_dbg ( ql_dbg_disc , vha , 0x20b5 ,
" RHBA identifier = %016llx. \n " ,
wwn_to_u64 ( ct_req - > req . rhba2 . hba_identifier ) ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x20b6 ,
entries , size ) ;
/* Execute MS IOCB */
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
ql_dbg ( ql_dbg_disc , vha , 0x20b7 ,
" RHBA issue IOCB failed (%d). \n " , rval ) ;
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " RHBA " ) ! =
QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
if ( ct_rsp - > header . reason_code = = CT_REASON_CANNOT_PERFORM & &
ct_rsp - > header . explanation_code = =
CT_EXPL_ALREADY_REGISTERED ) {
ql_dbg ( ql_dbg_disc , vha , 0x20b8 ,
" HBA already registered. \n " ) ;
rval = QLA_ALREADY_REGISTERED ;
} else {
ql_dbg ( ql_dbg_disc , vha , 0x2016 ,
" RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x \n " ,
ct_rsp - > header . reason_code ,
ct_rsp - > header . explanation_code ) ;
}
} else {
ql_dbg ( ql_dbg_disc , vha , 0x20b9 ,
" RHBA FDMI V2 exiting normally. \n " ) ;
}
return rval ;
}
2005-08-27 06:08:30 +04:00
/**
* qla2x00_fdmi_dhba ( ) -
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_fdmi_dhba ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
int rval ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
/* Issue RPA */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_fdmi_iocb ( vha , DHBA_REQ_SIZE ,
2005-08-27 06:08:30 +04:00
DHBA_RSP_SIZE ) ;
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_fdmi_req ( ha - > ct_sns , DHBA_CMD , DHBA_RSP_SIZE ) ;
2005-08-27 06:08:30 +04:00
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare FDMI command arguments -- portname. */
2008-11-06 21:40:19 +03:00
memcpy ( ct_req - > req . dhba . port_name , vha - > port_name , WWN_SIZE ) ;
2005-08-27 06:08:30 +04:00
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2036 ,
2013-08-27 09:37:27 +04:00
" DHBA portname = %8phN. \n " , ct_req - > req . dhba . port_name ) ;
2005-08-27 06:08:30 +04:00
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-08-27 06:08:30 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2037 ,
" DHBA issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " DHBA " ) ! =
2005-08-27 06:08:30 +04:00
QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
} else {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2038 ,
" DHBA exiting normally. \n " ) ;
2005-08-27 06:08:30 +04:00
}
return rval ;
}
/**
2014-09-25 13:16:46 +04:00
* qla2x00_fdmiv2_rpa ( ) -
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
*
* Returns 0 on success .
*/
static int
2014-09-25 13:16:46 +04:00
qla2x00_fdmiv2_rpa ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
int rval , alen ;
2014-09-25 13:16:46 +04:00
uint32_t size ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2005-08-27 06:08:30 +04:00
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2014-09-25 13:16:46 +04:00
void * entries ;
struct ct_fdmiv2_port_attr * eiter ;
2005-08-27 06:08:30 +04:00
struct init_cb_24xx * icb24 = ( struct init_cb_24xx * ) ha - > init_cb ;
2014-09-25 13:16:46 +04:00
struct new_utsname * p_sysid = NULL ;
2005-08-27 06:08:30 +04:00
/* Issue RPA */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_fdmi_iocb ( vha , 0 , RPA_RSP_SIZE ) ;
2005-08-27 06:08:30 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_fdmi_req ( ha - > ct_sns , RPA_CMD , RPA_RSP_SIZE ) ;
2005-08-27 06:08:30 +04:00
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare FDMI command arguments -- attribute block, attributes. */
2014-09-25 13:16:46 +04:00
memcpy ( ct_req - > req . rpa2 . port_name , vha - > port_name , WWN_SIZE ) ;
2005-08-27 06:08:30 +04:00
size = WWN_SIZE + 4 ;
/* Attributes */
2014-09-25 13:16:46 +04:00
ct_req - > req . rpa2 . attrs . count = cpu_to_be32 ( FDMIV2_PORT_ATTR_COUNT ) ;
entries = ct_req - > req . rpa2 . port_name ;
2005-08-27 06:08:30 +04:00
/* FC4 types. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_FC4_TYPES ) ;
eiter - > len = cpu_to_be16 ( 4 + 32 ) ;
2005-08-27 06:08:30 +04:00
eiter - > a . fc4_types [ 2 ] = 0x01 ;
size + = 4 + 32 ;
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20ba ,
2011-07-14 23:00:13 +04:00
" FC4_TYPES=%02x %02x. \n " ,
eiter - > a . fc4_types [ 2 ] ,
eiter - > a . fc4_types [ 1 ] ) ;
2005-08-27 06:08:30 +04:00
2017-06-21 23:48:45 +03:00
if ( vha - > flags . nvme_enabled ) {
eiter - > a . fc4_types [ 6 ] = 1 ; /* NVMe type 28h */
ql_dbg ( ql_dbg_disc , vha , 0x211f ,
" NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0. \n " ,
eiter - > a . fc4_types [ 6 ] ) ;
}
2005-08-27 06:08:30 +04:00
/* Supported speed. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_SUPPORT_SPEED ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
2012-02-09 23:15:34 +04:00
if ( IS_CNA_CAPABLE ( ha ) )
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
2009-01-05 22:18:11 +03:00
FDMI_PORT_SPEED_10GB ) ;
2014-02-26 13:15:06 +04:00
else if ( IS_QLA27XX ( ha ) )
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_32GB |
FDMI_PORT_SPEED_16GB |
2014-02-26 13:15:06 +04:00
FDMI_PORT_SPEED_8GB ) ;
2014-09-25 13:16:46 +04:00
else if ( IS_QLA2031 ( ha ) )
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_16GB |
FDMI_PORT_SPEED_8GB |
FDMI_PORT_SPEED_4GB ) ;
2009-01-05 22:18:11 +03:00
else if ( IS_QLA25XX ( ha ) )
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_8GB |
FDMI_PORT_SPEED_4GB |
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
2008-04-04 00:13:26 +04:00
else if ( IS_QLA24XX_TYPE ( ha ) )
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_4GB |
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
2005-08-27 06:08:30 +04:00
else if ( IS_QLA23XX ( ha ) )
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_1GB ) ;
2005-08-27 06:08:30 +04:00
else
2014-09-25 13:16:46 +04:00
eiter - > a . sup_speed = cpu_to_be32 (
2007-07-20 02:05:58 +04:00
FDMI_PORT_SPEED_1GB ) ;
2005-08-27 06:08:30 +04:00
size + = 4 + 4 ;
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20bb ,
" Supported Port Speed = %x. \n " , eiter - > a . sup_speed ) ;
2005-08-27 06:08:30 +04:00
/* Current speed. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_CURRENT_SPEED ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
2005-08-27 06:08:30 +04:00
switch ( ha - > link_data_rate ) {
2007-07-20 02:05:58 +04:00
case PORT_SPEED_1GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_1GB ) ;
2005-08-27 06:08:30 +04:00
break ;
2007-07-20 02:05:58 +04:00
case PORT_SPEED_2GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_2GB ) ;
2005-08-27 06:08:30 +04:00
break ;
2007-07-20 02:05:58 +04:00
case PORT_SPEED_4GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_4GB ) ;
2007-07-20 02:05:58 +04:00
break ;
2007-07-20 07:37:34 +04:00
case PORT_SPEED_8GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_8GB ) ;
2007-07-20 07:37:34 +04:00
break ;
2009-01-05 22:18:11 +03:00
case PORT_SPEED_10GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_10GB ) ;
2009-01-05 22:18:11 +03:00
break ;
2012-02-09 23:15:34 +04:00
case PORT_SPEED_16GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_16GB ) ;
2012-02-09 23:15:34 +04:00
break ;
2014-02-26 13:15:06 +04:00
case PORT_SPEED_32GB :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_32GB ) ;
2014-02-26 13:15:06 +04:00
break ;
2007-07-20 02:05:58 +04:00
default :
2014-09-25 13:16:46 +04:00
eiter - > a . cur_speed = cpu_to_be32 ( FDMI_PORT_SPEED_UNKNOWN ) ;
2005-08-27 06:08:30 +04:00
break ;
}
size + = 4 + 4 ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2017 ,
2014-09-25 13:16:46 +04:00
" Current_Speed = %x. \n " , eiter - > a . cur_speed ) ;
2005-08-27 06:08:30 +04:00
/* Max frame size. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_MAX_FRAME_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
eiter - > a . max_frame_size = IS_FWI2_CAPABLE ( ha ) ?
2008-04-25 02:21:29 +04:00
le16_to_cpu ( icb24 - > frame_payload_size ) :
le16_to_cpu ( ha - > init_cb - > frame_payload_size ) ;
2014-09-25 13:16:46 +04:00
eiter - > a . max_frame_size = cpu_to_be32 ( eiter - > a . max_frame_size ) ;
2005-08-27 06:08:30 +04:00
size + = 4 + 4 ;
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20bc ,
" Max_Frame_Size = %x. \n " , eiter - > a . max_frame_size ) ;
2005-08-27 06:08:30 +04:00
/* OS device name. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_OS_DEVICE_NAME ) ;
2013-02-08 10:57:55 +04:00
alen = strlen ( QLA2XXX_DRIVER_NAME ) ;
2014-09-25 13:16:46 +04:00
snprintf ( eiter - > a . os_dev_name , sizeof ( eiter - > a . os_dev_name ) ,
" %s:host%lu " , QLA2XXX_DRIVER_NAME , vha - > host_no ) ;
alen + = 4 - ( alen & 3 ) ;
2005-08-27 06:08:30 +04:00
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20be ,
" OS_Device_Name = %s. \n " , eiter - > a . os_dev_name ) ;
2005-08-27 06:08:30 +04:00
2006-10-02 23:00:45 +04:00
/* Hostname. */
2014-09-25 13:16:46 +04:00
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_HOST_NAME ) ;
p_sysid = utsname ( ) ;
if ( p_sysid ) {
snprintf ( eiter - > a . host_name , sizeof ( eiter - > a . host_name ) ,
" %s " , p_sysid - > nodename ) ;
} else {
2006-10-02 23:00:45 +04:00
snprintf ( eiter - > a . host_name , sizeof ( eiter - > a . host_name ) ,
2008-11-06 21:40:19 +03:00
" %s " , fc_host_system_hostname ( vha - > host ) ) ;
2006-10-02 23:00:45 +04:00
}
2014-09-25 13:16:46 +04:00
alen = strlen ( eiter - > a . host_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201a ,
2014-09-25 13:16:46 +04:00
" HostName=%s. \n " , eiter - > a . host_name ) ;
/* Node Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_NODE_NAME ) ;
memcpy ( eiter - > a . node_name , vha - > node_name , WWN_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
size + = 4 + WWN_SIZE ;
ql_dbg ( ql_dbg_disc , vha , 0x20c0 ,
" Node Name = %016llx. \n " , wwn_to_u64 ( eiter - > a . node_name ) ) ;
/* Port Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_NAME ) ;
memcpy ( eiter - > a . port_name , vha - > port_name , WWN_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
size + = 4 + WWN_SIZE ;
ql_dbg ( ql_dbg_disc , vha , 0x20c1 ,
" Port Name = %016llx. \n " , wwn_to_u64 ( eiter - > a . port_name ) ) ;
/* Port Symbolic Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_SYM_NAME ) ;
qla2x00_get_sym_node_name ( vha , eiter - > a . port_sym_name ,
sizeof ( eiter - > a . port_sym_name ) ) ;
alen = strlen ( eiter - > a . port_sym_name ) ;
alen + = 4 - ( alen & 3 ) ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
ql_dbg ( ql_dbg_disc , vha , 0x20c2 ,
" port symbolic name = %s \n " , eiter - > a . port_sym_name ) ;
/* Port Type */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_TYPE ) ;
eiter - > a . port_type = cpu_to_be32 ( NS_NX_PORT_TYPE ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20c3 ,
" Port Type = %x. \n " , eiter - > a . port_type ) ;
/* Class of Service */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_SUPP_COS ) ;
eiter - > a . port_supported_cos = cpu_to_be32 ( FC_CLASS_3 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20c4 ,
" Supported COS = %08x \n " , eiter - > a . port_supported_cos ) ;
/* Port Fabric Name */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_FABRIC_NAME ) ;
memcpy ( eiter - > a . fabric_name , vha - > fabric_node_name , WWN_SIZE ) ;
eiter - > len = cpu_to_be16 ( 4 + WWN_SIZE ) ;
size + = 4 + WWN_SIZE ;
ql_dbg ( ql_dbg_disc , vha , 0x20c5 ,
" Fabric Name = %016llx. \n " , wwn_to_u64 ( eiter - > a . fabric_name ) ) ;
/* FC4_type */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_FC4_TYPE ) ;
eiter - > a . port_fc4_type [ 0 ] = 0 ;
eiter - > a . port_fc4_type [ 1 ] = 0 ;
eiter - > a . port_fc4_type [ 2 ] = 1 ;
eiter - > a . port_fc4_type [ 3 ] = 0 ;
eiter - > len = cpu_to_be16 ( 4 + 32 ) ;
size + = 4 + 32 ;
ql_dbg ( ql_dbg_disc , vha , 0x20c6 ,
" Port Active FC4 Type = %02x %02x. \n " ,
eiter - > a . port_fc4_type [ 2 ] , eiter - > a . port_fc4_type [ 1 ] ) ;
2017-06-21 23:48:45 +03:00
if ( vha - > flags . nvme_enabled ) {
eiter - > a . port_fc4_type [ 4 ] = 0 ;
eiter - > a . port_fc4_type [ 5 ] = 0 ;
eiter - > a . port_fc4_type [ 6 ] = 1 ; /* NVMe type 28h */
ql_dbg ( ql_dbg_disc , vha , 0x2120 ,
" NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0. \n " ,
eiter - > a . port_fc4_type [ 6 ] ) ;
}
2014-09-25 13:16:46 +04:00
/* Port State */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_STATE ) ;
eiter - > a . port_state = cpu_to_be32 ( 1 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20c7 ,
" Port State = %x. \n " , eiter - > a . port_state ) ;
/* Number of Ports */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_COUNT ) ;
eiter - > a . num_ports = cpu_to_be32 ( 1 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
ql_dbg ( ql_dbg_disc , vha , 0x20c8 ,
" Number of ports = %x. \n " , eiter - > a . num_ports ) ;
/* Port Id */
eiter = entries + size ;
eiter - > type = cpu_to_be16 ( FDMI_PORT_ID ) ;
eiter - > a . port_id = cpu_to_be32 ( vha - > d_id . b24 ) ;
eiter - > len = cpu_to_be16 ( 4 + 4 ) ;
size + = 4 + 4 ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201c ,
2014-09-25 13:16:46 +04:00
" Port Id = %x. \n " , eiter - > a . port_id ) ;
2006-10-02 23:00:45 +04:00
2005-08-27 06:08:30 +04:00
/* Update MS request size. */
2008-11-06 21:40:19 +03:00
qla2x00_update_ms_fdmi_iocb ( vha , size + 16 ) ;
2005-08-27 06:08:30 +04:00
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2018 ,
2013-08-27 09:37:27 +04:00
" RPA portname= %8phN size=%d. \n " , ct_req - > req . rpa . port_name , size ) ;
2014-09-25 13:16:46 +04:00
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x20ca ,
2011-07-14 23:00:13 +04:00
entries , size ) ;
2005-08-27 06:08:30 +04:00
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2005-08-27 06:08:30 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20cb ,
" RPA FDMI v2 issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp , " RPA " ) ! =
2005-08-27 06:08:30 +04:00
QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
2014-09-25 13:16:46 +04:00
if ( ct_rsp - > header . reason_code = = CT_REASON_CANNOT_PERFORM & &
ct_rsp - > header . explanation_code = =
CT_EXPL_ALREADY_REGISTERED ) {
ql_dbg ( ql_dbg_disc , vha , 0x20ce ,
" RPA FDMI v2 already registered \n " ) ;
rval = QLA_ALREADY_REGISTERED ;
} else {
ql_dbg ( ql_dbg_disc , vha , 0x2020 ,
" RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x \n " ,
ct_rsp - > header . reason_code ,
ct_rsp - > header . explanation_code ) ;
}
2005-08-27 06:08:30 +04:00
} else {
2014-09-25 13:16:46 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x20cc ,
" RPA FDMI V2 exiting normally. \n " ) ;
2005-08-27 06:08:30 +04:00
}
return rval ;
}
/**
* qla2x00_fdmi_register ( ) -
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2005-08-27 06:08:30 +04:00
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_fdmi_register ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
2014-09-25 13:16:46 +04:00
int rval = QLA_FUNCTION_FAILED ;
struct qla_hw_data * ha = vha - > hw ;
2009-08-01 02:09:33 +04:00
2013-03-28 16:21:23 +04:00
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) | |
IS_QLAFX00 ( ha ) )
2009-08-01 02:09:33 +04:00
return QLA_FUNCTION_FAILED ;
2005-08-27 06:08:30 +04:00
2008-11-06 21:40:19 +03:00
rval = qla2x00_mgmt_svr_login ( vha ) ;
2005-08-27 06:08:30 +04:00
if ( rval )
return rval ;
2014-09-25 13:16:46 +04:00
rval = qla2x00_fdmiv2_rhba ( vha ) ;
if ( rval ) {
if ( rval ! = QLA_ALREADY_REGISTERED )
goto try_fdmi ;
rval = qla2x00_fdmi_dhba ( vha ) ;
if ( rval )
goto try_fdmi ;
rval = qla2x00_fdmiv2_rhba ( vha ) ;
if ( rval )
goto try_fdmi ;
}
rval = qla2x00_fdmiv2_rpa ( vha ) ;
if ( rval )
goto try_fdmi ;
goto out ;
try_fdmi :
2008-11-06 21:40:19 +03:00
rval = qla2x00_fdmi_rhba ( vha ) ;
2005-08-27 06:08:30 +04:00
if ( rval ) {
if ( rval ! = QLA_ALREADY_REGISTERED )
return rval ;
2008-11-06 21:40:19 +03:00
rval = qla2x00_fdmi_dhba ( vha ) ;
2005-08-27 06:08:30 +04:00
if ( rval )
return rval ;
2008-11-06 21:40:19 +03:00
rval = qla2x00_fdmi_rhba ( vha ) ;
2005-08-27 06:08:30 +04:00
if ( rval )
return rval ;
}
2008-11-06 21:40:19 +03:00
rval = qla2x00_fdmi_rpa ( vha ) ;
2014-09-25 13:16:46 +04:00
out :
2005-08-27 06:08:30 +04:00
return rval ;
}
2006-10-02 23:00:43 +04:00
/**
* qla2x00_gfpn_id ( ) - SNS Get Fabric Port Name ( GFPN_ID ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2006-10-02 23:00:43 +04:00
* @ list : switch info entries to populate
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_gfpn_id ( scsi_qla_host_t * vha , sw_info_t * list )
2006-10-02 23:00:43 +04:00
{
2012-02-09 23:15:57 +04:00
int rval = QLA_SUCCESS ;
2006-10-02 23:00:43 +04:00
uint16_t i ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-10-02 23:00:43 +04:00
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2006-10-02 23:00:43 +04:00
2007-07-20 02:05:57 +04:00
if ( ! IS_IIDMA_CAPABLE ( ha ) )
2006-10-02 23:00:43 +04:00
return QLA_FUNCTION_FAILED ;
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GFPN_ID_REQ_SIZE ;
arg . rsp_size = GFPN_ID_RSP_SIZE ;
arg . nport_handle = NPH_SNS ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2006-10-02 23:00:43 +04:00
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2006-10-02 23:00:43 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GFPN_ID_CMD ,
2006-10-02 23:00:43 +04:00
GFPN_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id */
ct_req - > req . port_id . port_id [ 0 ] = list [ i ] . d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = list [ i ] . d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = list [ i ] . d_id . b . al_pa ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2006-10-02 23:00:43 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2023 ,
" GFPN_ID issue IOCB failed (%d). \n " , rval ) ;
2012-02-09 23:16:00 +04:00
break ;
2008-11-06 21:40:19 +03:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp ,
2006-10-02 23:00:43 +04:00
" GFPN_ID " ) ! = QLA_SUCCESS ) {
rval = QLA_FUNCTION_FAILED ;
2012-02-09 23:16:00 +04:00
break ;
2006-10-02 23:00:43 +04:00
} else {
/* Save fabric portname */
memcpy ( list [ i ] . fabric_port_name ,
ct_rsp - > rsp . gfpn_id . port_name , WWN_SIZE ) ;
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
static inline struct ct_sns_req *
2013-06-25 19:27:28 +04:00
qla24xx_prep_ct_fm_req ( struct ct_sns_pkt * p , uint16_t cmd ,
2006-10-02 23:00:43 +04:00
uint16_t rsp_size )
{
2013-06-25 19:27:28 +04:00
memset ( p , 0 , sizeof ( struct ct_sns_pkt ) ) ;
2006-10-02 23:00:43 +04:00
2013-06-25 19:27:28 +04:00
p - > p . req . header . revision = 0x01 ;
p - > p . req . header . gs_type = 0xFA ;
p - > p . req . header . gs_subtype = 0x01 ;
p - > p . req . command = cpu_to_be16 ( cmd ) ;
p - > p . req . max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
2006-10-02 23:00:43 +04:00
2013-06-25 19:27:28 +04:00
return & p - > p . req ;
2006-10-02 23:00:43 +04:00
}
/**
* qla2x00_gpsc ( ) - FCS Get Port Speed Capabilities ( GPSC ) query .
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2006-10-02 23:00:43 +04:00
* @ list : switch info entries to populate
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_gpsc ( scsi_qla_host_t * vha , sw_info_t * list )
2006-10-02 23:00:43 +04:00
{
int rval ;
uint16_t i ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2017-01-20 09:28:00 +03:00
ms_iocb_entry_t * ms_pkt ;
2006-10-02 23:00:43 +04:00
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2006-10-02 23:00:43 +04:00
2007-07-20 02:05:57 +04:00
if ( ! IS_IIDMA_CAPABLE ( ha ) )
2006-10-02 23:00:43 +04:00
return QLA_FUNCTION_FAILED ;
2006-12-14 06:20:28 +03:00
if ( ! ha - > flags . gpsc_supported )
return QLA_FUNCTION_FAILED ;
2006-10-02 23:00:43 +04:00
2008-11-06 21:40:19 +03:00
rval = qla2x00_mgmt_svr_login ( vha ) ;
2006-10-02 23:00:43 +04:00
if ( rval )
return rval ;
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GPSC_REQ_SIZE ;
arg . rsp_size = GPSC_RSP_SIZE ;
arg . nport_handle = vha - > mgmt_svr_loop_id ;
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2006-10-02 23:00:43 +04:00
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = qla24xx_prep_ms_iocb ( vha , & arg ) ;
2006-10-02 23:00:43 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla24xx_prep_ct_fm_req ( ha - > ct_sns , GPSC_CMD ,
GPSC_RSP_SIZE ) ;
2006-10-02 23:00:43 +04:00
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_name */
memcpy ( ct_req - > req . gpsc . port_name , list [ i ] . fabric_port_name ,
WWN_SIZE ) ;
/* Execute MS IOCB */
2008-11-06 21:40:19 +03:00
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
2006-10-02 23:00:43 +04:00
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
/*EMPTY*/
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2059 ,
" GPSC issue IOCB failed (%d). \n " , rval ) ;
2008-11-06 21:40:19 +03:00
} else if ( ( rval = qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp ,
2006-12-14 06:20:28 +03:00
" GPSC " ) ) ! = QLA_SUCCESS ) {
/* FM command unsupported? */
if ( rval = = QLA_INVALID_COMMAND & &
2008-04-04 00:13:23 +04:00
( ct_rsp - > header . reason_code = =
CT_REASON_INVALID_COMMAND_CODE | |
ct_rsp - > header . reason_code = =
CT_REASON_COMMAND_UNSUPPORTED ) ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x205a ,
" GPSC command unsupported, disabling "
" query. \n " ) ;
2006-12-14 06:20:28 +03:00
ha - > flags . gpsc_supported = 0 ;
rval = QLA_FUNCTION_FAILED ;
break ;
}
2006-10-02 23:00:43 +04:00
rval = QLA_FUNCTION_FAILED ;
} else {
2007-08-13 21:13:18 +04:00
/* Save port-speed */
switch ( be16_to_cpu ( ct_rsp - > rsp . gpsc . speed ) ) {
case BIT_15 :
list [ i ] . fp_speed = PORT_SPEED_1GB ;
break ;
case BIT_14 :
list [ i ] . fp_speed = PORT_SPEED_2GB ;
break ;
case BIT_13 :
list [ i ] . fp_speed = PORT_SPEED_4GB ;
break ;
2009-06-03 20:55:22 +04:00
case BIT_12 :
list [ i ] . fp_speed = PORT_SPEED_10GB ;
break ;
2007-08-13 21:13:18 +04:00
case BIT_11 :
list [ i ] . fp_speed = PORT_SPEED_8GB ;
break ;
2012-11-21 11:40:39 +04:00
case BIT_10 :
list [ i ] . fp_speed = PORT_SPEED_16GB ;
break ;
2014-02-26 13:15:06 +04:00
case BIT_8 :
list [ i ] . fp_speed = PORT_SPEED_32GB ;
break ;
2007-08-13 21:13:18 +04:00
}
2006-10-02 23:00:43 +04:00
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x205b ,
" GPSC ext entry - fpn "
2013-08-27 09:37:27 +04:00
" %8phN speeds=%04x speed=%04x. \n " ,
list [ i ] . fabric_port_name ,
2007-08-13 21:13:18 +04:00
be16_to_cpu ( ct_rsp - > rsp . gpsc . speeds ) ,
2011-07-14 23:00:13 +04:00
be16_to_cpu ( ct_rsp - > rsp . gpsc . speed ) ) ;
2006-10-02 23:00:43 +04:00
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
return ( rval ) ;
}
2010-07-23 14:28:25 +04:00
/**
* qla2x00_gff_id ( ) - SNS Get FC - 4 Features ( GFF_ID ) query .
*
2018-01-24 03:33:51 +03:00
* @ vha : HA context
2010-07-23 14:28:25 +04:00
* @ list : switch info entries to populate
*
*/
void
qla2x00_gff_id ( scsi_qla_host_t * vha , sw_info_t * list )
{
int rval ;
uint16_t i ;
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
struct qla_hw_data * ha = vha - > hw ;
uint8_t fcp_scsi_features = 0 ;
2017-01-20 09:28:00 +03:00
struct ct_arg arg ;
2010-07-23 14:28:25 +04:00
2012-02-09 23:15:57 +04:00
for ( i = 0 ; i < ha - > max_fibre_devices ; i + + ) {
2010-07-23 14:28:25 +04:00
/* Set default FC4 Type as UNKNOWN so the default is to
* Process this port */
list [ i ] . fc4_type = FC4_TYPE_UNKNOWN ;
/* Do not attempt GFF_ID if we are not FWI_2 capable */
if ( ! IS_FWI2_CAPABLE ( ha ) )
continue ;
2017-01-20 09:28:00 +03:00
arg . iocb = ha - > ms_iocb ;
arg . req_dma = ha - > ct_sns_dma ;
arg . rsp_dma = ha - > ct_sns_dma ;
arg . req_size = GFF_ID_REQ_SIZE ;
arg . rsp_size = GFF_ID_RSP_SIZE ;
arg . nport_handle = NPH_SNS ;
2010-07-23 14:28:25 +04:00
/* Prepare common MS IOCB */
2017-01-20 09:28:00 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , & arg ) ;
2010-07-23 14:28:25 +04:00
/* Prepare CT request */
2013-06-25 19:27:28 +04:00
ct_req = qla2x00_prep_ct_req ( ha - > ct_sns , GFF_ID_CMD ,
2010-07-23 14:28:25 +04:00
GFF_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id */
ct_req - > req . port_id . port_id [ 0 ] = list [ i ] . d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = list [ i ] . d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = list [ i ] . d_id . b . al_pa ;
/* Execute MS IOCB */
rval = qla2x00_issue_iocb ( vha , ha - > ms_iocb , ha - > ms_iocb_dma ,
sizeof ( ms_iocb_entry_t ) ) ;
if ( rval ! = QLA_SUCCESS ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x205c ,
" GFF_ID issue IOCB failed (%d). \n " , rval ) ;
2010-07-23 14:28:25 +04:00
} else if ( qla2x00_chk_ms_status ( vha , ms_pkt , ct_rsp ,
2011-02-24 02:27:12 +03:00
" GFF_ID " ) ! = QLA_SUCCESS ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x205d ,
" GFF_ID IOCB status had a failure status code. \n " ) ;
2010-07-23 14:28:25 +04:00
} else {
fcp_scsi_features =
ct_rsp - > rsp . gff_id . fc4_features [ GFF_FCP_SCSI_OFFSET ] ;
fcp_scsi_features & = 0x0f ;
if ( fcp_scsi_features )
list [ i ] . fc4_type = FC4_TYPE_FCP_SCSI ;
else
list [ i ] . fc4_type = FC4_TYPE_OTHER ;
2017-06-21 23:48:44 +03:00
list [ i ] . fc4f_nvme =
ct_rsp - > rsp . gff_id . fc4_features [ GFF_NVME_OFFSET ] ;
list [ i ] . fc4f_nvme & = 0xf ;
2010-07-23 14:28:25 +04:00
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
}
2017-01-20 09:28:00 +03:00
/* GID_PN completion processing. */
void qla24xx_handle_gidpn_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
fc_port_t * fcport = ea - > fcport ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201d ,
2017-12-28 23:33:35 +03:00
" %s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d \n " ,
__func__ , fcport - > port_name , fcport - > disc_state ,
fcport - > fw_login_state , ea - > rc , fcport - > login_gen , ea - > sp - > gen2 ,
fcport - > rscn_gen , ea - > sp - > gen1 , fcport - > loop_id ) ;
2017-01-20 09:28:00 +03:00
2017-12-28 23:33:26 +03:00
if ( fcport - > disc_state = = DSC_DELETE_PEND )
return ;
2017-01-20 09:28:00 +03:00
if ( ea - > sp - > gen2 ! = fcport - > login_gen ) {
/* PLOGI/PRLI/LOGO came in while cmd was out.*/
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201e ,
2017-12-28 23:33:35 +03:00
" %s %8phC generation changed rscn %d|%d n " ,
2017-01-20 09:28:00 +03:00
__func__ , fcport - > port_name , fcport - > last_rscn_gen ,
2017-12-28 23:33:35 +03:00
fcport - > rscn_gen ) ;
2017-01-20 09:28:00 +03:00
return ;
}
if ( ! ea - > rc ) {
if ( ea - > sp - > gen1 = = fcport - > rscn_gen ) {
fcport - > scan_state = QLA_FCPORT_FOUND ;
fcport - > flags | = FCF_FABRIC_DEVICE ;
if ( fcport - > d_id . b24 = = ea - > id . b24 ) {
/* cable plugged into the same place */
switch ( vha - > host - > active_mode ) {
case MODE_TARGET :
2017-12-28 23:33:26 +03:00
if ( fcport - > fw_login_state = =
DSC_LS_PRLI_COMP ) {
u16 data [ 2 ] ;
/*
* Late RSCN was delivered .
* Remote port already login ' ed .
*/
ql_dbg ( ql_dbg_disc , vha , 0x201f ,
" %s %d %8phC post adisc \n " ,
__func__ , __LINE__ ,
fcport - > port_name ) ;
data [ 0 ] = data [ 1 ] = 0 ;
qla2x00_post_async_adisc_work (
vha , fcport , data ) ;
}
2017-01-20 09:28:00 +03:00
break ;
case MODE_INITIATOR :
case MODE_DUAL :
default :
2017-08-24 01:05:21 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x201f ,
" %s %d %8phC post %s \n " , __func__ ,
__LINE__ , fcport - > port_name ,
( atomic_read ( & fcport - > state ) = =
2017-12-28 23:33:15 +03:00
FCS_ONLINE ) ? " adisc " : " gnl " ) ;
2017-08-24 01:05:21 +03:00
2017-01-20 09:28:00 +03:00
if ( atomic_read ( & fcport - > state ) = =
2017-12-28 23:33:15 +03:00
FCS_ONLINE ) {
u16 data [ 2 ] ;
data [ 0 ] = data [ 1 ] = 0 ;
qla2x00_post_async_adisc_work (
vha , fcport , data ) ;
} else {
2017-08-24 01:05:21 +03:00
qla24xx_post_gnl_work ( vha ,
fcport ) ;
2017-12-28 23:33:15 +03:00
}
2017-01-20 09:28:00 +03:00
break ;
}
} else { /* fcport->d_id.b24 != ea->id.b24 */
fcport - > d_id . b24 = ea - > id . b24 ;
2017-12-28 23:33:26 +03:00
fcport - > id_changed = 1 ;
2017-12-05 01:45:00 +03:00
if ( fcport - > deleted ! = QLA_SESS_DELETED ) {
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2021 ,
2017-01-20 09:28:00 +03:00
" %s %d %8phC post del sess \n " ,
__func__ , __LINE__ , fcport - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2017-01-20 09:28:00 +03:00
}
}
} else { /* ea->sp->gen1 != fcport->rscn_gen */
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2022 ,
2017-01-20 09:28:00 +03:00
" %s %d %8phC post gidpn \n " ,
__func__ , __LINE__ , fcport - > port_name ) ;
/* rscn came in while cmd was out */
qla24xx_post_gidpn_work ( vha , fcport ) ;
}
} else { /* ea->rc */
/* cable pulled */
if ( ea - > sp - > gen1 = = fcport - > rscn_gen ) {
if ( ea - > sp - > gen2 = = fcport - > login_gen ) {
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2042 ,
2017-01-20 09:28:00 +03:00
" %s %d %8phC post del sess \n " , __func__ ,
__LINE__ , fcport - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2017-01-20 09:28:00 +03:00
} else {
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2045 ,
2017-01-20 09:28:00 +03:00
" %s %d %8phC login \n " , __func__ , __LINE__ ,
fcport - > port_name ) ;
qla24xx_fcport_handle_login ( vha , fcport ) ;
}
} else {
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2049 ,
2017-01-20 09:28:00 +03:00
" %s %d %8phC post gidpn \n " , __func__ , __LINE__ ,
fcport - > port_name ) ;
qla24xx_post_gidpn_work ( vha , fcport ) ;
}
}
} /* gidpn_event */
2017-01-20 09:28:04 +03:00
static void qla2x00_async_gidpn_sp_done ( void * s , int res )
2017-01-20 09:28:00 +03:00
{
2017-01-20 09:28:04 +03:00
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
2017-01-20 09:28:00 +03:00
fc_port_t * fcport = sp - > fcport ;
u8 * id = fcport - > ct_desc . ct_sns - > p . rsp . rsp . gid_pn . port_id ;
struct event_arg ea ;
2017-12-28 23:33:41 +03:00
fcport - > flags & = ~ ( FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE ) ;
2017-01-20 09:28:00 +03:00
memset ( & ea , 0 , sizeof ( ea ) ) ;
ea . fcport = fcport ;
ea . id . b . domain = id [ 0 ] ;
ea . id . b . area = id [ 1 ] ;
ea . id . b . al_pa = id [ 2 ] ;
ea . sp = sp ;
ea . rc = res ;
ea . event = FCME_GIDPN_DONE ;
2017-12-05 01:45:01 +03:00
if ( res = = QLA_FUNCTION_TIMEOUT ) {
ql_dbg ( ql_dbg_disc , sp - > vha , 0xffff ,
" Async done-%s WWPN %8phC timed out. \n " ,
sp - > name , fcport - > port_name ) ;
qla24xx_post_gidpn_work ( sp - > vha , fcport ) ;
sp - > free ( sp ) ;
return ;
} else if ( res ) {
ql_dbg ( ql_dbg_disc , sp - > vha , 0xffff ,
" Async done-%s fail res %x, WWPN %8phC \n " ,
sp - > name , res , fcport - > port_name ) ;
} else {
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s good WWPN %8phC ID %3phC \n " ,
sp - > name , fcport - > port_name , id ) ;
}
2017-01-20 09:28:00 +03:00
qla2x00_fcport_event_handler ( vha , & ea ) ;
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
}
int qla24xx_async_gidpn ( scsi_qla_host_t * vha , fc_port_t * fcport )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
2017-12-28 23:33:40 +03:00
if ( ! vha - > flags . online | | ( fcport - > flags & FCF_ASYNC_SENT ) )
return rval ;
2017-01-20 09:28:00 +03:00
fcport - > disc_state = DSC_GID_PN ;
fcport - > scan_state = QLA_FCPORT_SCAN ;
sp = qla2x00_get_sp ( vha , fcport , GFP_ATOMIC ) ;
if ( ! sp )
goto done ;
2017-12-28 23:33:40 +03:00
fcport - > flags | = FCF_ASYNC_SENT ;
2017-01-20 09:28:00 +03:00
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gidpn " ;
sp - > gen1 = fcport - > rscn_gen ;
sp - > gen2 = fcport - > login_gen ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( fcport - > ct_desc . ct_sns , GID_PN_CMD ,
GID_PN_RSP_SIZE ) ;
/* GIDPN req */
memcpy ( ct_req - > req . gid_pn . port_name , fcport - > port_name ,
WWN_SIZE ) ;
/* req & rsp use the same buffer */
sp - > u . iocb_cmd . u . ctarg . req = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . req_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . rsp = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . rsp_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . req_size = GID_PN_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GID_PN_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_gidpn_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x20a4 ,
" Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x. \n " ,
sp - > name , fcport - > port_name ,
sp - > handle , fcport - > loop_id , fcport - > d_id . b . domain ,
fcport - > d_id . b . area , fcport - > d_id . b . al_pa ) ;
2017-01-20 09:28:00 +03:00
return rval ;
done_free_sp :
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-12-28 23:33:40 +03:00
done :
2018-02-22 11:49:37 +03:00
fcport - > flags & = ~ FCF_ASYNC_ACTIVE ;
2017-01-20 09:28:00 +03:00
return rval ;
}
int qla24xx_post_gidpn_work ( struct scsi_qla_host * vha , fc_port_t * fcport )
{
struct qla_work_evt * e ;
2017-01-20 09:28:03 +03:00
int ls ;
2017-01-20 09:28:00 +03:00
2017-01-20 09:28:03 +03:00
ls = atomic_read ( & vha - > loop_state ) ;
if ( ( ( ls ! = LOOP_READY ) & & ( ls ! = LOOP_UP ) ) | |
2017-01-20 09:28:00 +03:00
test_bit ( UNLOADING , & vha - > dpc_flags ) )
return 0 ;
e = qla2x00_alloc_work ( vha , QLA_EVT_GIDPN ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . fcport . fcport = fcport ;
2017-12-28 23:33:41 +03:00
fcport - > flags | = FCF_ASYNC_ACTIVE ;
2017-01-20 09:28:00 +03:00
return qla2x00_post_work ( vha , e ) ;
}
int qla24xx_post_gpsc_work ( struct scsi_qla_host * vha , fc_port_t * fcport )
{
struct qla_work_evt * e ;
e = qla2x00_alloc_work ( vha , QLA_EVT_GPSC ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . fcport . fcport = fcport ;
2017-12-28 23:33:41 +03:00
fcport - > flags | = FCF_ASYNC_ACTIVE ;
2017-01-20 09:28:00 +03:00
return qla2x00_post_work ( vha , e ) ;
}
2017-12-28 23:33:26 +03:00
void qla24xx_handle_gpsc_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
struct fc_port * fcport = ea - > fcport ;
ql_dbg ( ql_dbg_disc , vha , 0x20d8 ,
2017-12-28 23:33:35 +03:00
" %s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d \n " ,
2017-12-28 23:33:26 +03:00
__func__ , fcport - > port_name , fcport - > disc_state ,
2017-12-28 23:33:35 +03:00
fcport - > fw_login_state , ea - > rc , ea - > sp - > gen2 , fcport - > login_gen ,
ea - > sp - > gen2 , fcport - > rscn_gen | ea - > sp - > gen1 , fcport - > loop_id ) ;
2017-12-28 23:33:26 +03:00
if ( fcport - > disc_state = = DSC_DELETE_PEND )
return ;
if ( ea - > sp - > gen2 ! = fcport - > login_gen ) {
/* target side must have changed it. */
ql_dbg ( ql_dbg_disc , vha , 0x20d3 ,
2017-12-28 23:33:35 +03:00
" %s %8phC generation changed \n " ,
__func__ , fcport - > port_name ) ;
2017-12-28 23:33:26 +03:00
return ;
} else if ( ea - > sp - > gen1 ! = fcport - > rscn_gen ) {
ql_dbg ( ql_dbg_disc , vha , 0x20d4 , " %s %d %8phC post gidpn \n " ,
__func__ , __LINE__ , fcport - > port_name ) ;
qla24xx_post_gidpn_work ( vha , fcport ) ;
return ;
}
2018-05-01 19:01:48 +03:00
qla_post_iidma_work ( vha , fcport ) ;
2017-12-28 23:33:26 +03:00
}
2017-01-20 09:28:04 +03:00
static void qla24xx_async_gpsc_sp_done ( void * s , int res )
2017-01-20 09:28:00 +03:00
{
2017-01-20 09:28:04 +03:00
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
2017-01-20 09:28:00 +03:00
struct qla_hw_data * ha = vha - > hw ;
fc_port_t * fcport = sp - > fcport ;
struct ct_sns_rsp * ct_rsp ;
struct event_arg ea ;
ct_rsp = & fcport - > ct_desc . ct_sns - > p . rsp ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2053 ,
2017-01-20 09:28:00 +03:00
" Async done-%s res %x, WWPN %8phC \n " ,
sp - > name , res , fcport - > port_name ) ;
if ( res = = ( DID_ERROR < < 16 ) ) {
/* entry status error */
goto done ;
} else if ( res ) {
if ( ( ct_rsp - > header . reason_code = =
CT_REASON_INVALID_COMMAND_CODE ) | |
( ct_rsp - > header . reason_code = =
2017-06-02 19:12:01 +03:00
CT_REASON_COMMAND_UNSUPPORTED ) ) {
ql_dbg ( ql_dbg_disc , vha , 0x2019 ,
" GPSC command unsupported, disabling query. \n " ) ;
2017-01-20 09:28:00 +03:00
ha - > flags . gpsc_supported = 0 ;
res = QLA_SUCCESS ;
}
} else {
switch ( be16_to_cpu ( ct_rsp - > rsp . gpsc . speed ) ) {
case BIT_15 :
fcport - > fp_speed = PORT_SPEED_1GB ;
break ;
case BIT_14 :
fcport - > fp_speed = PORT_SPEED_2GB ;
break ;
case BIT_13 :
fcport - > fp_speed = PORT_SPEED_4GB ;
break ;
case BIT_12 :
fcport - > fp_speed = PORT_SPEED_10GB ;
break ;
case BIT_11 :
fcport - > fp_speed = PORT_SPEED_8GB ;
break ;
case BIT_10 :
fcport - > fp_speed = PORT_SPEED_16GB ;
break ;
case BIT_8 :
fcport - > fp_speed = PORT_SPEED_32GB ;
break ;
}
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2054 ,
" Async-%s OUT WWPN %8phC speeds=%04x speed=%04x. \n " ,
sp - > name , fcport - > fabric_port_name ,
be16_to_cpu ( ct_rsp - > rsp . gpsc . speeds ) ,
be16_to_cpu ( ct_rsp - > rsp . gpsc . speed ) ) ;
2017-01-20 09:28:00 +03:00
}
done :
memset ( & ea , 0 , sizeof ( ea ) ) ;
ea . event = FCME_GPSC_DONE ;
ea . rc = res ;
ea . fcport = fcport ;
2017-12-28 23:33:26 +03:00
ea . sp = sp ;
2017-01-20 09:28:00 +03:00
qla2x00_fcport_event_handler ( vha , & ea ) ;
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
}
int qla24xx_async_gpsc ( scsi_qla_host_t * vha , fc_port_t * fcport )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
2017-12-28 23:33:40 +03:00
if ( ! vha - > flags . online | | ( fcport - > flags & FCF_ASYNC_SENT ) )
return rval ;
2017-01-20 09:28:00 +03:00
sp = qla2x00_get_sp ( vha , fcport , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gpsc " ;
sp - > gen1 = fcport - > rscn_gen ;
sp - > gen2 = fcport - > login_gen ;
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
/* CT_IU preamble */
ct_req = qla24xx_prep_ct_fm_req ( fcport - > ct_desc . ct_sns , GPSC_CMD ,
GPSC_RSP_SIZE ) ;
/* GPSC req */
2017-08-24 01:05:06 +03:00
memcpy ( ct_req - > req . gpsc . port_name , fcport - > fabric_port_name ,
2017-01-20 09:28:00 +03:00
WWN_SIZE ) ;
sp - > u . iocb_cmd . u . ctarg . req = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . req_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . rsp = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . rsp_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . req_size = GPSC_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GPSC_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = vha - > mgmt_svr_loop_id ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla24xx_async_gpsc_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x205e ,
" Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x. \n " ,
sp - > name , fcport - > port_name , sp - > handle ,
fcport - > loop_id , fcport - > d_id . b . domain ,
fcport - > d_id . b . area , fcport - > d_id . b . al_pa ) ;
2017-01-20 09:28:00 +03:00
return rval ;
done_free_sp :
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
fcport - > flags & = ~ FCF_ASYNC_SENT ;
2017-12-28 23:33:40 +03:00
done :
2018-02-22 11:49:37 +03:00
fcport - > flags & = ~ FCF_ASYNC_ACTIVE ;
2017-01-20 09:28:00 +03:00
return rval ;
}
int qla24xx_post_gpnid_work ( struct scsi_qla_host * vha , port_id_t * id )
{
struct qla_work_evt * e ;
if ( test_bit ( UNLOADING , & vha - > dpc_flags ) )
return 0 ;
e = qla2x00_alloc_work ( vha , QLA_EVT_GPNID ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . gpnid . id = * id ;
return qla2x00_post_work ( vha , e ) ;
}
2017-12-28 23:33:31 +03:00
void qla24xx_sp_unmap ( scsi_qla_host_t * vha , srb_t * sp )
2017-01-20 09:28:00 +03:00
{
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
}
void qla24xx_handle_gpnid_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
2017-12-05 01:45:05 +03:00
fc_port_t * fcport , * conflict , * t ;
2017-12-28 23:33:15 +03:00
u16 data [ 2 ] ;
2017-01-20 09:28:00 +03:00
2017-12-05 01:45:05 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d port_id: %06x \n " ,
__func__ , __LINE__ , ea - > id . b24 ) ;
2017-01-20 09:28:00 +03:00
2017-12-05 01:45:05 +03:00
if ( ea - > rc ) {
/* cable is disconnected */
list_for_each_entry_safe ( fcport , t , & vha - > vp_fcports , list ) {
if ( fcport - > d_id . b24 = = ea - > id . b24 ) {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC DS %d \n " ,
__func__ , __LINE__ ,
fcport - > port_name ,
fcport - > disc_state ) ;
fcport - > scan_state = QLA_FCPORT_SCAN ;
switch ( fcport - > disc_state ) {
case DSC_DELETED :
case DSC_DELETE_PEND :
break ;
default :
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC post del sess \n " ,
__func__ , __LINE__ ,
fcport - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2017-12-05 01:45:05 +03:00
break ;
}
}
2017-06-02 19:11:56 +03:00
}
2017-01-20 09:28:00 +03:00
} else {
2017-12-05 01:45:05 +03:00
/* cable is connected */
fcport = qla2x00_find_fcport_by_wwpn ( vha , ea - > port_name , 1 ) ;
if ( fcport ) {
list_for_each_entry_safe ( conflict , t , & vha - > vp_fcports ,
list ) {
if ( ( conflict - > d_id . b24 = = ea - > id . b24 ) & &
( fcport ! = conflict ) ) {
/* 2 fcports with conflict Nport ID or
* an existing fcport is having nport ID
* conflict with new fcport .
*/
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC DS %d \n " ,
__func__ , __LINE__ ,
conflict - > port_name ,
conflict - > disc_state ) ;
conflict - > scan_state = QLA_FCPORT_SCAN ;
switch ( conflict - > disc_state ) {
case DSC_DELETED :
case DSC_DELETE_PEND :
break ;
default :
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC post del sess \n " ,
__func__ , __LINE__ ,
conflict - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion
2017-12-05 01:45:05 +03:00
( conflict ) ;
break ;
}
}
}
2017-01-20 09:28:00 +03:00
2017-12-05 01:45:05 +03:00
fcport - > rscn_gen + + ;
fcport - > scan_state = QLA_FCPORT_FOUND ;
fcport - > flags | = FCF_FABRIC_DEVICE ;
switch ( fcport - > disc_state ) {
case DSC_LOGIN_COMPLETE :
/* recheck session is still intact. */
ql_dbg ( ql_dbg_disc , vha , 0x210d ,
" %s %d %8phC revalidate session with ADISC \n " ,
__func__ , __LINE__ , fcport - > port_name ) ;
2017-12-28 23:33:15 +03:00
data [ 0 ] = data [ 1 ] = 0 ;
qla2x00_post_async_adisc_work ( vha , fcport ,
data ) ;
2017-12-05 01:45:05 +03:00
break ;
case DSC_DELETED :
ql_dbg ( ql_dbg_disc , vha , 0x210d ,
" %s %d %8phC login \n " , __func__ , __LINE__ ,
fcport - > port_name ) ;
fcport - > d_id = ea - > id ;
qla24xx_fcport_handle_login ( vha , fcport ) ;
break ;
case DSC_DELETE_PEND :
fcport - > d_id = ea - > id ;
break ;
default :
fcport - > d_id = ea - > id ;
break ;
}
} else {
list_for_each_entry_safe ( conflict , t , & vha - > vp_fcports ,
list ) {
if ( conflict - > d_id . b24 = = ea - > id . b24 ) {
/* 2 fcports with conflict Nport ID or
* an existing fcport is having nport ID
* conflict with new fcport .
*/
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC DS %d \n " ,
__func__ , __LINE__ ,
conflict - > port_name ,
conflict - > disc_state ) ;
conflict - > scan_state = QLA_FCPORT_SCAN ;
switch ( conflict - > disc_state ) {
case DSC_DELETED :
case DSC_DELETE_PEND :
break ;
default :
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC post del sess \n " ,
__func__ , __LINE__ ,
conflict - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion
2017-12-05 01:45:05 +03:00
( conflict ) ;
break ;
}
}
}
/* create new fcport */
ql_dbg ( ql_dbg_disc , vha , 0x2065 ,
" %s %d %8phC post new sess \n " ,
__func__ , __LINE__ , ea - > port_name ) ;
qla24xx_post_newsess_work ( vha , & ea - > id ,
2017-12-28 23:33:26 +03:00
ea - > port_name , NULL , NULL , FC4_TYPE_UNKNOWN ) ;
2017-12-05 01:45:05 +03:00
}
2017-01-20 09:28:00 +03:00
}
}
2017-01-20 09:28:04 +03:00
static void qla2x00_async_gpnid_sp_done ( void * s , int res )
2017-01-20 09:28:00 +03:00
{
2017-01-20 09:28:04 +03:00
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
2017-01-20 09:28:00 +03:00
struct ct_sns_req * ct_req =
( struct ct_sns_req * ) sp - > u . iocb_cmd . u . ctarg . req ;
struct ct_sns_rsp * ct_rsp =
( struct ct_sns_rsp * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
struct event_arg ea ;
struct qla_work_evt * e ;
2017-12-05 01:45:02 +03:00
unsigned long flags ;
2017-01-20 09:28:00 +03:00
2017-12-05 01:45:00 +03:00
if ( res )
ql_dbg ( ql_dbg_disc , vha , 0x2066 ,
2017-12-05 01:45:02 +03:00
" Async done-%s fail res %x rscn gen %d ID %3phC. %8phC \n " ,
sp - > name , res , sp - > gen1 , ct_req - > req . port_id . port_id ,
2017-12-05 01:45:00 +03:00
ct_rsp - > rsp . gpn_id . port_name ) ;
else
ql_dbg ( ql_dbg_disc , vha , 0x2066 ,
2017-12-05 01:45:02 +03:00
" Async done-%s good rscn gen %d ID %3phC. %8phC \n " ,
sp - > name , sp - > gen1 , ct_req - > req . port_id . port_id ,
2017-12-05 01:45:00 +03:00
ct_rsp - > rsp . gpn_id . port_name ) ;
2017-01-20 09:28:00 +03:00
memset ( & ea , 0 , sizeof ( ea ) ) ;
memcpy ( ea . port_name , ct_rsp - > rsp . gpn_id . port_name , WWN_SIZE ) ;
ea . sp = sp ;
ea . id . b . domain = ct_req - > req . port_id . port_id [ 0 ] ;
ea . id . b . area = ct_req - > req . port_id . port_id [ 1 ] ;
ea . id . b . al_pa = ct_req - > req . port_id . port_id [ 2 ] ;
ea . rc = res ;
ea . event = FCME_GPNID_DONE ;
2017-12-05 01:45:02 +03:00
spin_lock_irqsave ( & vha - > hw - > tgt . sess_lock , flags ) ;
list_del ( & sp - > elem ) ;
spin_unlock_irqrestore ( & vha - > hw - > tgt . sess_lock , flags ) ;
2017-12-05 01:45:01 +03:00
if ( res ) {
2017-12-05 01:45:05 +03:00
if ( res = = QLA_FUNCTION_TIMEOUT ) {
2017-12-05 01:45:01 +03:00
qla24xx_post_gpnid_work ( sp - > vha , & ea . id ) ;
2017-12-05 01:45:05 +03:00
sp - > free ( sp ) ;
return ;
}
2017-12-05 01:45:02 +03:00
} else if ( sp - > gen1 ) {
2017-12-05 01:45:05 +03:00
/* There was another RSCN for this Nport ID */
2017-12-05 01:45:02 +03:00
qla24xx_post_gpnid_work ( sp - > vha , & ea . id ) ;
sp - > free ( sp ) ;
return ;
2017-12-05 01:45:01 +03:00
}
2017-01-20 09:28:00 +03:00
qla2x00_fcport_event_handler ( vha , & ea ) ;
2017-12-28 23:33:31 +03:00
e = qla2x00_alloc_work ( vha , QLA_EVT_UNMAP ) ;
2017-01-20 09:28:00 +03:00
if ( ! e ) {
/* please ignore kernel warning. otherwise, we have mem leak. */
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
return ;
}
e - > u . iosb . sp = sp ;
qla2x00_post_work ( vha , e ) ;
}
/* Get WWPN with Nport ID. */
int qla24xx_async_gpnid ( scsi_qla_host_t * vha , port_id_t * id )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
2017-12-05 01:45:02 +03:00
srb_t * sp , * tsp ;
2017-01-20 09:28:00 +03:00
struct ct_sns_pkt * ct_sns ;
2017-12-05 01:45:02 +03:00
unsigned long flags ;
2017-01-20 09:28:00 +03:00
if ( ! vha - > flags . online )
goto done ;
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gpnid " ;
2017-12-05 01:45:02 +03:00
sp - > u . iocb_cmd . u . ctarg . id = * id ;
sp - > gen1 = 0 ;
2017-01-20 09:28:00 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
2017-12-05 01:45:02 +03:00
spin_lock_irqsave ( & vha - > hw - > tgt . sess_lock , flags ) ;
list_for_each_entry ( tsp , & vha - > gpnid_list , elem ) {
if ( tsp - > u . iocb_cmd . u . ctarg . id . b24 = = id - > b24 ) {
tsp - > gen1 + + ;
spin_unlock_irqrestore ( & vha - > hw - > tgt . sess_lock , flags ) ;
sp - > free ( sp ) ;
goto done ;
}
}
list_add_tail ( & sp - > elem , & vha - > gpnid_list ) ;
spin_unlock_irqrestore ( & vha - > hw - > tgt . sess_lock , flags ) ;
2017-01-20 09:28:00 +03:00
sp - > u . iocb_cmd . u . ctarg . req = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . req_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
2017-06-02 19:12:01 +03:00
ql_log ( ql_log_warn , vha , 0xd041 ,
" Failed to allocate ct_sns request. \n " ) ;
2017-01-20 09:28:00 +03:00
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . rsp = dma_alloc_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) , & sp - > u . iocb_cmd . u . ctarg . rsp_dma ,
GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
2017-06-02 19:12:01 +03:00
ql_log ( ql_log_warn , vha , 0xd042 ,
" Failed to allocate ct_sns request. \n " ) ;
2017-01-20 09:28:00 +03:00
goto done_free_sp ;
}
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
memset ( ct_sns , 0 , sizeof ( * ct_sns ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( ct_sns , GPN_ID_CMD , GPN_ID_RSP_SIZE ) ;
/* GPN_ID req */
ct_req - > req . port_id . port_id [ 0 ] = id - > b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = id - > b . area ;
ct_req - > req . port_id . port_id [ 2 ] = id - > b . al_pa ;
sp - > u . iocb_cmd . u . ctarg . req_size = GPN_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GPN_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
sp - > done = qla2x00_async_gpnid_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
2017-06-02 19:12:01 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x2067 ,
" Async-%s hdl=%x ID %3phC. \n " , sp - > name ,
sp - > handle , ct_req - > req . port_id . port_id ) ;
2017-01-20 09:28:00 +03:00
return rval ;
done_free_sp :
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
2017-01-20 09:28:04 +03:00
sp - > free ( sp ) ;
2017-01-20 09:28:00 +03:00
done :
return rval ;
}
2017-06-21 23:48:44 +03:00
void qla24xx_handle_gffid_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
fc_port_t * fcport = ea - > fcport ;
qla24xx_post_gnl_work ( vha , fcport ) ;
}
void qla24xx_async_gffid_sp_done ( void * s , int res )
{
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
fc_port_t * fcport = sp - > fcport ;
struct ct_sns_rsp * ct_rsp ;
struct event_arg ea ;
ql_dbg ( ql_dbg_disc , vha , 0x2133 ,
" Async done-%s res %x ID %x. %8phC \n " ,
sp - > name , res , fcport - > d_id . b24 , fcport - > port_name ) ;
fcport - > flags & = ~ FCF_ASYNC_SENT ;
ct_rsp = & fcport - > ct_desc . ct_sns - > p . rsp ;
/*
* FC - GS - 7 , 5.2 .3 .12 FC - 4 Features - format
* The format of the FC - 4 Features object , as defined by the FC - 4 ,
* Shall be an array of 4 - bit values , one for each type code value
*/
if ( ! res ) {
if ( ct_rsp - > rsp . gff_id . fc4_features [ GFF_FCP_SCSI_OFFSET ] & 0xf ) {
/* w1 b00:03 */
fcport - > fc4_type =
ct_rsp - > rsp . gff_id . fc4_features [ GFF_FCP_SCSI_OFFSET ] ;
fcport - > fc4_type & = 0xf ;
}
if ( ct_rsp - > rsp . gff_id . fc4_features [ GFF_NVME_OFFSET ] & 0xf ) {
/* w5 [00:03]/28h */
fcport - > fc4f_nvme =
ct_rsp - > rsp . gff_id . fc4_features [ GFF_NVME_OFFSET ] ;
fcport - > fc4f_nvme & = 0xf ;
}
}
memset ( & ea , 0 , sizeof ( ea ) ) ;
ea . sp = sp ;
ea . fcport = sp - > fcport ;
ea . rc = res ;
ea . event = FCME_GFFID_DONE ;
qla2x00_fcport_event_handler ( vha , & ea ) ;
sp - > free ( sp ) ;
}
/* Get FC4 Feature with Nport ID. */
int qla24xx_async_gffid ( scsi_qla_host_t * vha , fc_port_t * fcport )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
2017-12-28 23:33:40 +03:00
if ( ! vha - > flags . online | | ( fcport - > flags & FCF_ASYNC_SENT ) )
2017-06-21 23:48:44 +03:00
return rval ;
sp = qla2x00_get_sp ( vha , fcport , GFP_KERNEL ) ;
if ( ! sp )
return rval ;
fcport - > flags | = FCF_ASYNC_SENT ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gffid " ;
sp - > gen1 = fcport - > rscn_gen ;
sp - > gen2 = fcport - > login_gen ;
2018-03-21 00:36:14 +03:00
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
2017-06-21 23:48:44 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( fcport - > ct_desc . ct_sns , GFF_ID_CMD ,
GFF_ID_RSP_SIZE ) ;
ct_req - > req . gff_id . port_id [ 0 ] = fcport - > d_id . b . domain ;
ct_req - > req . gff_id . port_id [ 1 ] = fcport - > d_id . b . area ;
ct_req - > req . gff_id . port_id [ 2 ] = fcport - > d_id . b . al_pa ;
sp - > u . iocb_cmd . u . ctarg . req = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . req_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . rsp = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . rsp_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . req_size = GFF_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GFF_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > done = qla24xx_async_gffid_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
ql_dbg ( ql_dbg_disc , vha , 0x2132 ,
" Async-%s hdl=%x %8phC. \n " , sp - > name ,
sp - > handle , fcport - > port_name ) ;
return rval ;
done_free_sp :
sp - > free ( sp ) ;
fcport - > flags & = ~ FCF_ASYNC_SENT ;
return rval ;
}
2017-12-28 23:33:26 +03:00
/* GPN_FT + GNN_FT*/
static int qla2x00_is_a_vp ( scsi_qla_host_t * vha , u64 wwn )
{
struct qla_hw_data * ha = vha - > hw ;
scsi_qla_host_t * vp ;
unsigned long flags ;
u64 twwn ;
int rc = 0 ;
if ( ! ha - > num_vhosts )
return 0 ;
spin_lock_irqsave ( & ha - > vport_slock , flags ) ;
list_for_each_entry ( vp , & ha - > vp_list , list ) {
twwn = wwn_to_u64 ( vp - > port_name ) ;
if ( wwn = = twwn ) {
rc = 1 ;
break ;
}
}
spin_unlock_irqrestore ( & ha - > vport_slock , flags ) ;
return rc ;
}
void qla24xx_async_gnnft_done ( scsi_qla_host_t * vha , srb_t * sp )
{
fc_port_t * fcport ;
u32 i , rc ;
bool found ;
struct fab_scan_rp * rp ;
2017-12-28 23:33:35 +03:00
unsigned long flags ;
2018-05-01 19:01:47 +03:00
u8 recheck = 0 ;
2017-12-28 23:33:26 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s enter \n " , __func__ ) ;
if ( sp - > gen1 ! = vha - > hw - > base_qpair - > chip_reset ) {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s scan stop due to chip reset %x/%x \n " ,
sp - > name , sp - > gen1 , vha - > hw - > base_qpair - > chip_reset ) ;
goto out ;
}
rc = sp - > rc ;
if ( rc ) {
2017-12-28 23:33:39 +03:00
vha - > scan . scan_retry + + ;
if ( vha - > scan . scan_retry < MAX_SCAN_RETRIES ) {
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
} else {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Fabric scan failed on all retries. \n " ) ;
}
2017-12-28 23:33:26 +03:00
goto out ;
}
2017-12-28 23:33:39 +03:00
vha - > scan . scan_retry = 0 ;
2017-12-28 23:33:26 +03:00
list_for_each_entry ( fcport , & vha - > vp_fcports , list )
fcport - > scan_state = QLA_FCPORT_SCAN ;
for ( i = 0 ; i < vha - > hw - > max_fibre_devices ; i + + ) {
u64 wwn ;
rp = & vha - > scan . l [ i ] ;
found = false ;
wwn = wwn_to_u64 ( rp - > port_name ) ;
if ( wwn = = 0 )
continue ;
if ( ! memcmp ( rp - > port_name , vha - > port_name , WWN_SIZE ) )
continue ;
/* Bypass reserved domain fields. */
if ( ( rp - > id . b . domain & 0xf0 ) = = 0xf0 )
continue ;
/* Bypass virtual ports of the same host. */
if ( qla2x00_is_a_vp ( vha , wwn ) )
continue ;
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
if ( memcmp ( rp - > port_name , fcport - > port_name , WWN_SIZE ) )
continue ;
2018-05-01 19:01:47 +03:00
fcport - > rscn_rcvd = 0 ;
2017-12-28 23:33:26 +03:00
fcport - > scan_state = QLA_FCPORT_FOUND ;
found = true ;
/*
* If device was not a fabric device before .
*/
if ( ( fcport - > flags & FCF_FABRIC_DEVICE ) = = 0 ) {
qla2x00_clear_loop_id ( fcport ) ;
fcport - > flags | = FCF_FABRIC_DEVICE ;
2018-05-01 19:01:46 +03:00
} else if ( fcport - > d_id . b24 ! = rp - > id . b24 ) {
qlt_schedule_sess_for_deletion ( fcport ) ;
2017-12-28 23:33:26 +03:00
}
2018-05-01 19:01:46 +03:00
fcport - > d_id . b24 = rp - > id . b24 ;
2017-12-28 23:33:26 +03:00
break ;
}
if ( ! found ) {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s %d %8phC post new sess \n " ,
__func__ , __LINE__ , rp - > port_name ) ;
qla24xx_post_newsess_work ( vha , & rp - > id , rp - > port_name ,
2018-03-21 09:09:40 +03:00
rp - > node_name , NULL , rp - > fc4type ) ;
2017-12-28 23:33:26 +03:00
}
}
/*
* Logout all previous fabric dev marked lost , except FCP2 devices .
*/
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
2018-05-01 19:01:47 +03:00
if ( ( fcport - > flags & FCF_FABRIC_DEVICE ) = = 0 ) {
fcport - > rscn_rcvd = 0 ;
2017-12-28 23:33:26 +03:00
continue ;
2018-05-01 19:01:47 +03:00
}
2017-12-28 23:33:26 +03:00
2017-12-28 23:33:35 +03:00
if ( fcport - > scan_state ! = QLA_FCPORT_FOUND ) {
2018-05-01 19:01:47 +03:00
fcport - > rscn_rcvd = 0 ;
2017-12-28 23:33:26 +03:00
if ( ( qla_dual_mode_enabled ( vha ) | |
qla_ini_mode_enabled ( vha ) ) & &
atomic_read ( & fcport - > state ) = = FCS_ONLINE ) {
qla2x00_mark_device_lost ( vha , fcport ,
ql2xplogiabsentdevice , 0 ) ;
2017-12-28 23:33:35 +03:00
2017-12-28 23:33:26 +03:00
if ( fcport - > loop_id ! = FC_NO_LOOP_ID & &
2017-12-28 23:33:35 +03:00
( fcport - > flags & FCF_FCP2_DEVICE ) = = 0 ) {
2017-12-28 23:33:26 +03:00
ql_dbg ( ql_dbg_disc , vha , 0x20f0 ,
" %s %d %8phC post del sess \n " ,
__func__ , __LINE__ ,
fcport - > port_name ) ;
2017-12-28 23:33:43 +03:00
qlt_schedule_sess_for_deletion ( fcport ) ;
2017-12-28 23:33:26 +03:00
continue ;
}
}
2018-05-01 19:01:47 +03:00
} else {
if ( fcport - > rscn_rcvd | |
fcport - > disc_state ! = DSC_LOGIN_COMPLETE ) {
fcport - > rscn_rcvd = 0 ;
qla24xx_fcport_handle_login ( vha , fcport ) ;
}
}
2017-12-28 23:33:26 +03:00
}
2018-05-01 19:01:47 +03:00
recheck = 1 ;
2017-12-28 23:33:26 +03:00
out :
2017-12-28 23:33:31 +03:00
qla24xx_sp_unmap ( vha , sp ) ;
2017-12-28 23:33:35 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2018-05-01 19:01:47 +03:00
if ( recheck ) {
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
if ( fcport - > rscn_rcvd ) {
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
break ;
}
}
}
2017-12-28 23:33:26 +03:00
}
2018-03-21 09:09:40 +03:00
static void qla2x00_find_free_fcp_nvme_slot ( struct scsi_qla_host * vha ,
struct srb * sp )
2017-12-28 23:33:26 +03:00
{
2018-03-21 09:09:40 +03:00
struct qla_hw_data * ha = vha - > hw ;
int num_fibre_dev = ha - > max_fibre_devices ;
2017-12-28 23:33:26 +03:00
struct ct_sns_req * ct_req =
( struct ct_sns_req * ) sp - > u . iocb_cmd . u . ctarg . req ;
struct ct_sns_gpnft_rsp * ct_rsp =
( struct ct_sns_gpnft_rsp * ) sp - > u . iocb_cmd . u . ctarg . rsp ;
2018-01-05 18:50:37 +03:00
struct ct_sns_gpn_ft_data * d ;
2017-12-28 23:33:26 +03:00
struct fab_scan_rp * rp ;
2018-03-21 09:09:40 +03:00
u16 cmd = be16_to_cpu ( ct_req - > command ) ;
u8 fc4_type = sp - > gen2 ;
2017-12-28 23:33:26 +03:00
int i , j , k ;
2018-03-21 09:09:40 +03:00
port_id_t id ;
u8 found ;
u64 wwn ;
j = 0 ;
for ( i = 0 ; i < num_fibre_dev ; i + + ) {
d = & ct_rsp - > entries [ i ] ;
id . b . rsvd_1 = 0 ;
id . b . domain = d - > port_id [ 0 ] ;
id . b . area = d - > port_id [ 1 ] ;
id . b . al_pa = d - > port_id [ 2 ] ;
wwn = wwn_to_u64 ( d - > port_name ) ;
if ( id . b24 = = 0 | | wwn = = 0 )
continue ;
if ( fc4_type = = FC4_TYPE_FCP_SCSI ) {
if ( cmd = = GPN_FT_CMD ) {
rp = & vha - > scan . l [ j ] ;
rp - > id = id ;
memcpy ( rp - > port_name , d - > port_name , 8 ) ;
j + + ;
rp - > fc4type = FS_FC4TYPE_FCP ;
} else {
for ( k = 0 ; k < num_fibre_dev ; k + + ) {
rp = & vha - > scan . l [ k ] ;
if ( id . b24 = = rp - > id . b24 ) {
memcpy ( rp - > node_name ,
d - > port_name , 8 ) ;
break ;
}
}
}
} else {
/* Search if the fibre device supports FC4_TYPE_NVME */
if ( cmd = = GPN_FT_CMD ) {
found = 0 ;
for ( k = 0 ; k < num_fibre_dev ; k + + ) {
rp = & vha - > scan . l [ k ] ;
if ( ! memcmp ( rp - > port_name ,
d - > port_name , 8 ) ) {
/*
* Supports FC - NVMe & FCP
*/
rp - > fc4type | = FS_FC4TYPE_NVME ;
found = 1 ;
break ;
}
}
/* We found new FC-NVMe only port */
if ( ! found ) {
for ( k = 0 ; k < num_fibre_dev ; k + + ) {
rp = & vha - > scan . l [ k ] ;
if ( wwn_to_u64 ( rp - > port_name ) ) {
continue ;
} else {
rp - > id = id ;
memcpy ( rp - > port_name ,
d - > port_name , 8 ) ;
rp - > fc4type =
FS_FC4TYPE_NVME ;
break ;
}
}
}
} else {
for ( k = 0 ; k < num_fibre_dev ; k + + ) {
rp = & vha - > scan . l [ k ] ;
if ( id . b24 = = rp - > id . b24 ) {
memcpy ( rp - > node_name ,
d - > port_name , 8 ) ;
break ;
}
}
}
}
}
}
static void qla2x00_async_gpnft_gnnft_sp_done ( void * s , int res )
{
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
struct qla_work_evt * e ;
struct ct_sns_req * ct_req =
( struct ct_sns_req * ) sp - > u . iocb_cmd . u . ctarg . req ;
2017-12-28 23:33:26 +03:00
u16 cmd = be16_to_cpu ( ct_req - > command ) ;
2018-03-21 09:09:40 +03:00
u8 fc4_type = sp - > gen2 ;
unsigned long flags ;
2017-12-28 23:33:26 +03:00
/* gen2 field is holding the fc4type */
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async done-%s res %x FC4Type %x \n " ,
sp - > name , res , sp - > gen2 ) ;
2017-12-28 23:33:33 +03:00
if ( res ) {
unsigned long flags ;
sp - > free ( sp ) ;
2017-12-28 23:33:35 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
2017-12-28 23:33:39 +03:00
vha - > scan . scan_retry + + ;
2017-12-28 23:33:35 +03:00
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:39 +03:00
if ( vha - > scan . scan_retry < MAX_SCAN_RETRIES ) {
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
qla2xxx_wake_dpc ( vha ) ;
} else {
ql_dbg ( ql_dbg_disc , sp - > vha , 0xffff ,
" Async done-%s rescan failed on all retries \n " ,
sp - > name ) ;
}
2017-12-28 23:33:33 +03:00
return ;
}
2018-03-21 09:09:40 +03:00
if ( ! res )
qla2x00_find_free_fcp_nvme_slot ( vha , sp ) ;
2017-12-28 23:33:26 +03:00
2018-03-21 09:09:40 +03:00
if ( ( fc4_type = = FC4_TYPE_FCP_SCSI ) & & vha - > flags . nvme_enabled & &
cmd = = GNN_FT_CMD ) {
del_timer ( & sp - > u . iocb_cmd . timer ) ;
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:26 +03:00
2018-03-21 09:09:40 +03:00
e = qla2x00_alloc_work ( vha , QLA_EVT_GPNFT ) ;
if ( ! e ) {
/*
* please ignore kernel warning . Otherwise ,
* we have mem leak .
*/
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
2017-12-28 23:33:26 +03:00
}
2018-03-21 09:09:40 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async done-%s unable to alloc work element \n " ,
sp - > name ) ;
sp - > free ( sp ) ;
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
return ;
2017-12-28 23:33:26 +03:00
}
2018-03-21 09:09:40 +03:00
e - > u . gpnft . fc4_type = FC4_TYPE_NVME ;
sp - > rc = res ;
e - > u . gpnft . sp = sp ;
qla2x00_post_work ( vha , e ) ;
return ;
2017-12-28 23:33:26 +03:00
}
if ( cmd = = GPN_FT_CMD )
e = qla2x00_alloc_work ( vha , QLA_EVT_GPNFT_DONE ) ;
else
e = qla2x00_alloc_work ( vha , QLA_EVT_GNNFT_DONE ) ;
if ( ! e ) {
/* please ignore kernel warning. Otherwise, we have mem leak. */
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async done-%s unable to alloc work element \n " ,
sp - > name ) ;
sp - > free ( sp ) ;
2017-12-28 23:33:33 +03:00
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
2017-12-28 23:33:26 +03:00
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
return ;
}
sp - > rc = res ;
e - > u . iosb . sp = sp ;
qla2x00_post_work ( vha , e ) ;
}
/*
* Get WWNN list for fc4_type
*
* It is assumed the same SRB is re - used from GPNFT to avoid
* mem free & re - alloc
*/
static int qla24xx_async_gnnft ( scsi_qla_host_t * vha , struct srb * sp ,
u8 fc4_type )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
struct ct_sns_pkt * ct_sns ;
2018-03-21 09:09:40 +03:00
unsigned long flags ;
2017-12-28 23:33:26 +03:00
2017-12-28 23:33:35 +03:00
if ( ! vha - > flags . online ) {
2018-03-21 09:09:40 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:35 +03:00
vha - > scan . scan_flags & = ~ SF_SCANNING ;
2018-03-21 09:09:40 +03:00
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:26 +03:00
goto done_free_sp ;
2017-12-28 23:33:35 +03:00
}
2017-12-28 23:33:26 +03:00
if ( ! sp - > u . iocb_cmd . u . ctarg . req | | ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xffff ,
" %s: req %p rsp %p are not setup \n " ,
__func__ , sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . rsp ) ;
2018-03-21 09:09:40 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:35 +03:00
vha - > scan . scan_flags & = ~ SF_SCANNING ;
2018-03-21 09:09:40 +03:00
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:26 +03:00
WARN_ON ( 1 ) ;
goto done_free_sp ;
}
2018-03-21 09:09:40 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xfffff ,
" %s: FC4Type %x, CT-PASSTRHU %s command ctarg rsp size %d, ctarg req size %d \n " ,
__func__ , fc4_type , sp - > name , sp - > u . iocb_cmd . u . ctarg . rsp_size ,
sp - > u . iocb_cmd . u . ctarg . req_size ) ;
2017-12-28 23:33:26 +03:00
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gnnft " ;
sp - > gen1 = vha - > hw - > base_qpair - > chip_reset ;
sp - > gen2 = fc4_type ;
2018-03-21 00:36:14 +03:00
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
2017-12-28 23:33:26 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
memset ( sp - > u . iocb_cmd . u . ctarg . rsp , 0 , sp - > u . iocb_cmd . u . ctarg . rsp_size ) ;
memset ( sp - > u . iocb_cmd . u . ctarg . req , 0 , sp - > u . iocb_cmd . u . ctarg . req_size ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( ct_sns , GNN_FT_CMD ,
sp - > u . iocb_cmd . u . ctarg . rsp_size ) ;
/* GPN_FT req */
ct_req - > req . gpn_ft . port_type = fc4_type ;
sp - > u . iocb_cmd . u . ctarg . req_size = GNN_FT_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > done = qla2x00_async_gpnft_gnnft_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s hdl=%x FC4Type %x. \n " , sp - > name ,
sp - > handle , ct_req - > req . gpn_ft . port_type ) ;
return rval ;
done_free_sp :
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
sp - > free ( sp ) ;
return rval ;
} /* GNNFT */
void qla24xx_async_gpnft_done ( scsi_qla_host_t * vha , srb_t * sp )
{
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s enter \n " , __func__ ) ;
del_timer ( & sp - > u . iocb_cmd . timer ) ;
qla24xx_async_gnnft ( vha , sp , sp - > gen2 ) ;
}
/* Get WWPN list for certain fc4_type */
2018-03-21 09:09:40 +03:00
int qla24xx_async_gpnft ( scsi_qla_host_t * vha , u8 fc4_type , srb_t * sp )
2017-12-28 23:33:26 +03:00
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
struct ct_sns_pkt * ct_sns ;
u32 rspsz ;
2017-12-28 23:33:35 +03:00
unsigned long flags ;
2017-12-28 23:33:26 +03:00
2018-03-21 09:09:40 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s enter \n " , __func__ ) ;
2017-12-28 23:33:26 +03:00
if ( ! vha - > flags . online )
return rval ;
2017-12-28 23:33:35 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
if ( vha - > scan . scan_flags & SF_SCANNING ) {
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
ql_dbg ( ql_dbg_disc , vha , 0xffff , " scan active \n " ) ;
2017-12-28 23:33:26 +03:00
return rval ;
2017-12-28 23:33:35 +03:00
}
vha - > scan . scan_flags | = SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:26 +03:00
2018-03-21 09:09:40 +03:00
if ( fc4_type = = FC4_TYPE_FCP_SCSI ) {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s: Performing FCP Scan \n " , __func__ ) ;
if ( sp )
sp - > free ( sp ) ; /* should not happen */
sp = qla2x00_get_sp ( vha , NULL , GFP_KERNEL ) ;
if ( ! sp ) {
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
return rval ;
}
sp - > u . iocb_cmd . u . ctarg . req = dma_zalloc_coherent (
& vha - > hw - > pdev - > dev , sizeof ( struct ct_sns_pkt ) ,
& sp - > u . iocb_cmd . u . ctarg . req_dma , GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . req ) {
ql_log ( ql_log_warn , vha , 0xffff ,
" Failed to allocate ct_sns request. \n " ) ;
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . req_size = GPN_FT_REQ_SIZE ;
rspsz = sizeof ( struct ct_sns_gpnft_rsp ) +
( ( vha - > hw - > max_fibre_devices - 1 ) *
sizeof ( struct ct_sns_gpn_ft_data ) ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = dma_zalloc_coherent (
& vha - > hw - > pdev - > dev , rspsz ,
& sp - > u . iocb_cmd . u . ctarg . rsp_dma , GFP_KERNEL ) ;
if ( ! sp - > u . iocb_cmd . u . ctarg . rsp ) {
ql_log ( ql_log_warn , vha , 0xffff ,
" Failed to allocate ct_sns request. \n " ) ;
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_SCANNING ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
goto done_free_sp ;
}
sp - > u . iocb_cmd . u . ctarg . rsp_size = rspsz ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s scan list size %d \n " , __func__ , vha - > scan . size ) ;
memset ( vha - > scan . l , 0 , vha - > scan . size ) ;
} else if ( ! sp ) {
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" NVME scan did not provide SP \n " ) ;
2017-12-28 23:33:35 +03:00
return rval ;
}
2017-12-28 23:33:26 +03:00
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gpnft " ;
sp - > gen1 = vha - > hw - > base_qpair - > chip_reset ;
sp - > gen2 = fc4_type ;
2018-03-21 00:36:14 +03:00
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
2017-12-28 23:33:26 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
rspsz = sizeof ( struct ct_sns_gpnft_rsp ) +
( ( vha - > hw - > max_fibre_devices - 1 ) *
sizeof ( struct ct_sns_gpn_ft_data ) ) ;
ct_sns = ( struct ct_sns_pkt * ) sp - > u . iocb_cmd . u . ctarg . req ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( ct_sns , GPN_FT_CMD , rspsz ) ;
/* GPN_FT req */
ct_req - > req . gpn_ft . port_type = fc4_type ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > done = qla2x00_async_gpnft_gnnft_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
2017-12-28 23:33:35 +03:00
if ( rval ! = QLA_SUCCESS ) {
2018-03-21 09:09:40 +03:00
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:35 +03:00
vha - > scan . scan_flags & = ~ SF_SCANNING ;
2018-03-21 09:09:40 +03:00
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
2017-12-28 23:33:26 +03:00
goto done_free_sp ;
2017-12-28 23:33:35 +03:00
}
2017-12-28 23:33:26 +03:00
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s hdl=%x FC4Type %x. \n " , sp - > name ,
sp - > handle , ct_req - > req . gpn_ft . port_type ) ;
return rval ;
done_free_sp :
if ( sp - > u . iocb_cmd . u . ctarg . req ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . req ,
sp - > u . iocb_cmd . u . ctarg . req_dma ) ;
sp - > u . iocb_cmd . u . ctarg . req = NULL ;
}
if ( sp - > u . iocb_cmd . u . ctarg . rsp ) {
dma_free_coherent ( & vha - > hw - > pdev - > dev ,
sizeof ( struct ct_sns_pkt ) ,
sp - > u . iocb_cmd . u . ctarg . rsp ,
sp - > u . iocb_cmd . u . ctarg . rsp_dma ) ;
sp - > u . iocb_cmd . u . ctarg . rsp = NULL ;
}
sp - > free ( sp ) ;
return rval ;
}
2017-12-28 23:33:35 +03:00
void qla_scan_work_fn ( struct work_struct * work )
{
struct fab_scan * s = container_of ( to_delayed_work ( work ) ,
struct fab_scan , scan_work ) ;
struct scsi_qla_host * vha = container_of ( s , struct scsi_qla_host ,
scan ) ;
unsigned long flags ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" %s: schedule loop resync \n " , __func__ ) ;
set_bit ( LOCAL_LOOP_UPDATE , & vha - > dpc_flags ) ;
set_bit ( LOOP_RESYNC_NEEDED , & vha - > dpc_flags ) ;
qla2xxx_wake_dpc ( vha ) ;
spin_lock_irqsave ( & vha - > work_lock , flags ) ;
vha - > scan . scan_flags & = ~ SF_QUEUED ;
spin_unlock_irqrestore ( & vha - > work_lock , flags ) ;
}
2017-12-28 23:33:26 +03:00
/* GNN_ID */
void qla24xx_handle_gnnid_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
qla24xx_post_gnl_work ( vha , ea - > fcport ) ;
}
static void qla2x00_async_gnnid_sp_done ( void * s , int res )
{
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
fc_port_t * fcport = sp - > fcport ;
u8 * node_name = fcport - > ct_desc . ct_sns - > p . rsp . rsp . gnn_id . node_name ;
struct event_arg ea ;
u64 wwnn ;
fcport - > flags & = ~ FCF_ASYNC_SENT ;
wwnn = wwn_to_u64 ( node_name ) ;
if ( wwnn )
memcpy ( fcport - > node_name , node_name , WWN_SIZE ) ;
memset ( & ea , 0 , sizeof ( ea ) ) ;
ea . fcport = fcport ;
ea . sp = sp ;
ea . rc = res ;
ea . event = FCME_GNNID_DONE ;
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s res %x, WWPN %8phC %8phC \n " ,
sp - > name , res , fcport - > port_name , fcport - > node_name ) ;
qla2x00_fcport_event_handler ( vha , & ea ) ;
sp - > free ( sp ) ;
}
int qla24xx_async_gnnid ( scsi_qla_host_t * vha , fc_port_t * fcport )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
2017-12-28 23:33:40 +03:00
if ( ! vha - > flags . online | | ( fcport - > flags & FCF_ASYNC_SENT ) )
return rval ;
2017-12-28 23:33:26 +03:00
fcport - > disc_state = DSC_GNN_ID ;
sp = qla2x00_get_sp ( vha , fcport , GFP_ATOMIC ) ;
if ( ! sp )
goto done ;
2017-12-28 23:33:40 +03:00
fcport - > flags | = FCF_ASYNC_SENT ;
2017-12-28 23:33:26 +03:00
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gnnid " ;
sp - > gen1 = fcport - > rscn_gen ;
sp - > gen2 = fcport - > login_gen ;
2018-03-21 00:36:14 +03:00
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
2017-12-28 23:33:26 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( fcport - > ct_desc . ct_sns , GNN_ID_CMD ,
GNN_ID_RSP_SIZE ) ;
/* GNN_ID req */
ct_req - > req . port_id . port_id [ 0 ] = fcport - > d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = fcport - > d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = fcport - > d_id . b . al_pa ;
/* req & rsp use the same buffer */
sp - > u . iocb_cmd . u . ctarg . req = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . req_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . rsp = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . rsp_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . req_size = GNN_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GNN_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > done = qla2x00_async_gnnid_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - %8phC hdl=%x loopid=%x portid %06x. \n " ,
sp - > name , fcport - > port_name ,
sp - > handle , fcport - > loop_id , fcport - > d_id . b24 ) ;
return rval ;
done_free_sp :
sp - > free ( sp ) ;
2017-12-28 23:33:40 +03:00
done :
2017-12-28 23:33:26 +03:00
return rval ;
}
int qla24xx_post_gnnid_work ( struct scsi_qla_host * vha , fc_port_t * fcport )
{
struct qla_work_evt * e ;
int ls ;
ls = atomic_read ( & vha - > loop_state ) ;
if ( ( ( ls ! = LOOP_READY ) & & ( ls ! = LOOP_UP ) ) | |
test_bit ( UNLOADING , & vha - > dpc_flags ) )
return 0 ;
e = qla2x00_alloc_work ( vha , QLA_EVT_GNNID ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . fcport . fcport = fcport ;
return qla2x00_post_work ( vha , e ) ;
}
/* GPFN_ID */
void qla24xx_handle_gfpnid_event ( scsi_qla_host_t * vha , struct event_arg * ea )
{
fc_port_t * fcport = ea - > fcport ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
2017-12-28 23:33:35 +03:00
" %s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d \n " ,
__func__ , fcport - > port_name , fcport - > disc_state ,
fcport - > fw_login_state , ea - > rc , fcport - > login_gen , ea - > sp - > gen2 ,
fcport - > rscn_gen , ea - > sp - > gen1 , vha - > fcport_count ) ;
2017-12-28 23:33:26 +03:00
if ( fcport - > disc_state = = DSC_DELETE_PEND )
return ;
if ( ea - > sp - > gen2 ! = fcport - > login_gen ) {
/* target side must have changed it. */
ql_dbg ( ql_dbg_disc , vha , 0x20d3 ,
2017-12-28 23:33:35 +03:00
" %s %8phC generation changed \n " ,
__func__ , fcport - > port_name ) ;
2017-12-28 23:33:26 +03:00
return ;
} else if ( ea - > sp - > gen1 ! = fcport - > rscn_gen ) {
ql_dbg ( ql_dbg_disc , vha , 0x20d4 , " %s %d %8phC post gidpn \n " ,
__func__ , __LINE__ , fcport - > port_name ) ;
qla24xx_post_gidpn_work ( vha , fcport ) ;
return ;
}
qla24xx_post_gpsc_work ( vha , fcport ) ;
}
static void qla2x00_async_gfpnid_sp_done ( void * s , int res )
{
struct srb * sp = s ;
struct scsi_qla_host * vha = sp - > vha ;
fc_port_t * fcport = sp - > fcport ;
u8 * fpn = fcport - > ct_desc . ct_sns - > p . rsp . rsp . gfpn_id . port_name ;
struct event_arg ea ;
u64 wwn ;
wwn = wwn_to_u64 ( fpn ) ;
if ( wwn )
memcpy ( fcport - > fabric_port_name , fpn , WWN_SIZE ) ;
memset ( & ea , 0 , sizeof ( ea ) ) ;
ea . fcport = fcport ;
ea . sp = sp ;
ea . rc = res ;
ea . event = FCME_GFPNID_DONE ;
ql_dbg ( ql_dbg_disc , vha , 0x204f ,
" Async done-%s res %x, WWPN %8phC %8phC \n " ,
sp - > name , res , fcport - > port_name , fcport - > fabric_port_name ) ;
qla2x00_fcport_event_handler ( vha , & ea ) ;
sp - > free ( sp ) ;
}
int qla24xx_async_gfpnid ( scsi_qla_host_t * vha , fc_port_t * fcport )
{
int rval = QLA_FUNCTION_FAILED ;
struct ct_sns_req * ct_req ;
srb_t * sp ;
2017-12-28 23:33:40 +03:00
if ( ! vha - > flags . online | | ( fcport - > flags & FCF_ASYNC_SENT ) )
return rval ;
2017-12-28 23:33:26 +03:00
sp = qla2x00_get_sp ( vha , fcport , GFP_ATOMIC ) ;
if ( ! sp )
goto done ;
sp - > type = SRB_CT_PTHRU_CMD ;
sp - > name = " gfpnid " ;
sp - > gen1 = fcport - > rscn_gen ;
sp - > gen2 = fcport - > login_gen ;
2018-03-21 00:36:14 +03:00
sp - > u . iocb_cmd . timeout = qla2x00_async_iocb_timeout ;
2017-12-28 23:33:26 +03:00
qla2x00_init_timer ( sp , qla2x00_get_async_timeout ( vha ) + 2 ) ;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req ( fcport - > ct_desc . ct_sns , GFPN_ID_CMD ,
GFPN_ID_RSP_SIZE ) ;
/* GFPN_ID req */
ct_req - > req . port_id . port_id [ 0 ] = fcport - > d_id . b . domain ;
ct_req - > req . port_id . port_id [ 1 ] = fcport - > d_id . b . area ;
ct_req - > req . port_id . port_id [ 2 ] = fcport - > d_id . b . al_pa ;
/* req & rsp use the same buffer */
sp - > u . iocb_cmd . u . ctarg . req = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . req_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . rsp = fcport - > ct_desc . ct_sns ;
sp - > u . iocb_cmd . u . ctarg . rsp_dma = fcport - > ct_desc . ct_sns_dma ;
sp - > u . iocb_cmd . u . ctarg . req_size = GFPN_ID_REQ_SIZE ;
sp - > u . iocb_cmd . u . ctarg . rsp_size = GFPN_ID_RSP_SIZE ;
sp - > u . iocb_cmd . u . ctarg . nport_handle = NPH_SNS ;
sp - > done = qla2x00_async_gfpnid_sp_done ;
rval = qla2x00_start_sp ( sp ) ;
if ( rval ! = QLA_SUCCESS )
goto done_free_sp ;
ql_dbg ( ql_dbg_disc , vha , 0xffff ,
" Async-%s - %8phC hdl=%x loopid=%x portid %06x. \n " ,
sp - > name , fcport - > port_name ,
sp - > handle , fcport - > loop_id , fcport - > d_id . b24 ) ;
return rval ;
done_free_sp :
sp - > free ( sp ) ;
fcport - > flags & = ~ FCF_ASYNC_SENT ;
2017-12-28 23:33:40 +03:00
done :
2017-12-28 23:33:26 +03:00
return rval ;
}
int qla24xx_post_gfpnid_work ( struct scsi_qla_host * vha , fc_port_t * fcport )
{
struct qla_work_evt * e ;
int ls ;
ls = atomic_read ( & vha - > loop_state ) ;
if ( ( ( ls ! = LOOP_READY ) & & ( ls ! = LOOP_UP ) ) | |
test_bit ( UNLOADING , & vha - > dpc_flags ) )
return 0 ;
e = qla2x00_alloc_work ( vha , QLA_EVT_GFPNID ) ;
if ( ! e )
return QLA_FUNCTION_FAILED ;
e - > u . fcport . fcport = fcport ;
return qla2x00_post_work ( vha , e ) ;
}