2005-04-17 02:20:36 +04:00
/*
2005-10-27 22:10:08 +04:00
* QLogic Fibre Channel HBA Driver
2013-02-08 10:57:54 +04:00
* Copyright ( c ) 2003 - 2013 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"
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 * ) ;
/**
2005-07-06 21:30:47 +04:00
* qla2x00_prep_ms_iocb ( ) - Prepare common MS / CT IOCB fields for SNS CT query .
2005-04-17 02:20:36 +04:00
* @ ha : HA context
* @ req_size : request size in bytes
* @ rsp_size : response size in bytes
*
* Returns a pointer to the @ ha ' s ms_iocb .
*/
2005-07-06 21:30:47 +04:00
void *
2008-11-06 21:40:19 +03:00
qla2x00_prep_ms_iocb ( scsi_qla_host_t * vha , uint32_t req_size , uint32_t rsp_size )
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 ;
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 ;
SET_TARGET_ID ( ha , ms_pkt - > loop_id , SIMPLE_NAME_SERVER ) ;
ms_pkt - > control_flags = __constant_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 ) ;
2005-04-17 02:20:36 +04:00
ms_pkt - > cmd_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
ms_pkt - > total_dsd_count = __constant_cpu_to_le16 ( 2 ) ;
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 ) ;
}
2005-07-06 21:30:47 +04:00
/**
* qla24xx_prep_ms_iocb ( ) - Prepare common CT IOCB fields for SNS CT query .
* @ ha : HA context
* @ 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_iocb ( scsi_qla_host_t * vha , uint32_t req_size , uint32_t rsp_size )
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 ;
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 ;
ct_pkt - > nport_handle = __constant_cpu_to_le16 ( NPH_SNS ) ;
2008-02-29 01:06:11 +03:00
ct_pkt - > timeout = cpu_to_le16 ( ha - > r_a_tov / 10 * 2 ) ;
2005-07-06 21:30:47 +04:00
ct_pkt - > cmd_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
ct_pkt - > rsp_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
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-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 .
* @ ct_req : CT request buffer
* @ cmd : GS command
* @ rsp_size : response size in bytes
*
* Returns a pointer to the intitialized @ ct_req .
*/
static inline struct ct_sns_req *
qla2x00_prep_ct_req ( struct ct_sns_req * ct_req , uint16_t cmd , uint16_t rsp_size )
{
memset ( ct_req , 0 , sizeof ( struct ct_sns_pkt ) ) ;
ct_req - > header . revision = 0x01 ;
ct_req - > header . gs_type = 0xFC ;
ct_req - > header . gs_subtype = 0x02 ;
ct_req - > command = cpu_to_be16 ( cmd ) ;
ct_req - > max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
return ( ct_req ) ;
}
2005-07-06 21:30:47 +04:00
static 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 ;
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 ! =
__constant_cpu_to_be16 ( CT_ACCEPT_RESPONSE ) ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2077 ,
" %s failed rejected request on port_id: "
" %02x%02x%02x. \n " , routine ,
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 ) ;
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 ;
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 .
* @ ha : HA context
* @ 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 ;
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
/* Issue GA_NXT */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GA_NXT_REQ_SIZE ,
2007-07-20 02:06:00 +04:00
GA_NXT_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GA_NXT_CMD ,
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 ,
" GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
2005-04-17 02:20:36 +04:00
" pn %02x%02x%02x%02x%02x%02x%02x%02x "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2005-04-17 02:20:36 +04:00
fcport - > node_name [ 0 ] , fcport - > node_name [ 1 ] ,
fcport - > node_name [ 2 ] , fcport - > node_name [ 3 ] ,
fcport - > node_name [ 4 ] , fcport - > node_name [ 5 ] ,
fcport - > node_name [ 6 ] , fcport - > node_name [ 7 ] ,
fcport - > port_name [ 0 ] , fcport - > port_name [ 1 ] ,
fcport - > port_name [ 2 ] , fcport - > port_name [ 3 ] ,
fcport - > port_name [ 4 ] , fcport - > port_name [ 5 ] ,
fcport - > port_name [ 6 ] , fcport - > port_name [ 7 ] ,
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 .
* @ ha : HA context
* @ 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 ;
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 ) ;
2005-04-17 02:20:36 +04:00
/* Issue GID_PT */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GID_PT_REQ_SIZE ,
2012-02-09 23:15:57 +04:00
gid_pt_rsp_size ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GID_PT_CMD ,
2012-02-09 23:15:57 +04:00
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 .
* @ ha : HA context
* @ 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 ;
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
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 */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GPN_ID_REQ_SIZE ,
2005-04-17 02:20:36 +04:00
GPN_ID_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GPN_ID_CMD ,
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 .
* @ ha : HA context
* @ 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 ;
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
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 */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GNN_ID_REQ_SIZE ,
2005-04-17 02:20:36 +04:00
GNN_ID_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GNN_ID_CMD ,
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 ,
" GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
" pn %02x%02x%02x%02x%02x%02x%02X%02x "
2005-04-17 02:20:36 +04:00
" portid=%02x%02x%02x. \n " ,
list [ i ] . node_name [ 0 ] , list [ i ] . node_name [ 1 ] ,
list [ i ] . node_name [ 2 ] , list [ i ] . node_name [ 3 ] ,
list [ i ] . node_name [ 4 ] , list [ i ] . node_name [ 5 ] ,
list [ i ] . node_name [ 6 ] , list [ i ] . node_name [ 7 ] ,
list [ i ] . port_name [ 0 ] , list [ i ] . port_name [ 1 ] ,
list [ i ] . port_name [ 2 ] , list [ i ] . port_name [ 3 ] ,
list [ i ] . port_name [ 4 ] , list [ i ] . port_name [ 5 ] ,
list [ i ] . port_name [ 6 ] , list [ i ] . port_name [ 7 ] ,
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_rft_id ( ) - SNS Register FC - 4 TYPEs ( RFT_ID ) supported by the HBA .
* @ ha : HA context
*
* 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
{
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
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
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_rft_id ( vha ) ;
2005-04-17 02:20:36 +04:00
/* Issue RFT_ID */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , RFT_ID_REQ_SIZE ,
2007-07-20 02:06:00 +04:00
RFT_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , RFT_ID_CMD ,
RFT_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* 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 */
/* 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 , 0x2043 ,
" RFT_ID 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 , " RFT_ID " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
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 , 0x2044 ,
" RFT_ID exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
/**
* qla2x00_rff_id ( ) - SNS Register FC - 4 Features ( RFF_ID ) supported by the HBA .
* @ ha : HA context
*
* Returns 0 on success .
*/
int
2008-11-06 21:40:19 +03:00
qla2x00_rff_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
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
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 ) ;
}
/* Issue RFF_ID */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , RFF_ID_REQ_SIZE ,
2007-07-20 02:06:00 +04:00
RFF_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , RFF_ID_CMD ,
RFF_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
2008-11-06 21:40:19 +03:00
ct_req - > req . rff_id . port_id [ 0 ] = vha - > d_id . b . domain ;
ct_req - > req . rff_id . port_id [ 1 ] = vha - > d_id . b . area ;
ct_req - > req . rff_id . port_id [ 2 ] = vha - > d_id . b . al_pa ;
2005-04-17 02:20:36 +04:00
2012-05-15 22:34:28 +04:00
qlt_rff_id ( vha , ct_req ) ;
2005-04-17 02:20:36 +04:00
ct_req - > req . rff_id . fc4_type = 0x08 ; /* SCSI - FCP */
/* 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 , 0x2047 ,
" RFF_ID 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 , " RFF_ID " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
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 , 0x2048 ,
" RFF_ID exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
/**
* qla2x00_rnn_id ( ) - SNS Register Node Name ( RNN_ID ) of the HBA .
* @ ha : HA context
*
* 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
{
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
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
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
return qla2x00_sns_rnn_id ( vha ) ;
2005-04-17 02:20:36 +04:00
/* Issue RNN_ID */
/* Prepare common MS IOCB */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , RNN_ID_REQ_SIZE ,
2007-07-20 02:06:00 +04:00
RNN_ID_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , RNN_ID_CMD ,
RNN_ID_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* 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 ;
2005-04-17 02:20:36 +04:00
2008-11-06 21:40:19 +03:00
memcpy ( ct_req - > req . rnn_id . node_name , vha - > node_name , WWN_SIZE ) ;
2005-04-17 02:20:36 +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-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 , 0x204d ,
" RNN_ID 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 , " RNN_ID " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
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 , 0x204e ,
" RNN_ID exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
2006-10-02 23:00:44 +04:00
void
2008-11-06 21:40:19 +03:00
qla2x00_get_sym_node_name ( scsi_qla_host_t * vha , uint8_t * snn )
2006-10-02 23:00:44 +04:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2006-10-02 23:00:44 +04:00
sprintf ( snn , " %s FW:v%d.%02d.%02d DVR:v%s " , ha - > model_number ,
ha - > fw_major_version , ha - > fw_minor_version ,
ha - > fw_subminor_version , qla2x00_version_str ) ;
}
2005-04-17 02:20:36 +04:00
/**
* qla2x00_rsnn_nn ( ) - SNS Register Symbolic Node Name ( RSNN_NN ) of the HBA .
* @ ha : HA context
*
* 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
{
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
ms_iocb_entry_t * ms_pkt ;
struct ct_sns_req * ct_req ;
struct ct_sns_rsp * ct_rsp ;
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 ) ;
}
/* Issue RSNN_NN */
/* 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_iocb ( vha , 0 , RSNN_NN_RSP_SIZE ) ;
2005-04-17 02:20:36 +04:00
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , RSNN_NN_CMD ,
RSNN_NN_RSP_SIZE ) ;
ct_rsp = & ha - > ct_sns - > p . rsp ;
/* 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 */
2008-11-06 21:40:19 +03:00
qla2x00_get_sym_node_name ( vha , ct_req - > req . rsnn_nn . sym_node_name ) ;
2005-04-17 02:20:36 +04:00
/* Calculate SNN length */
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
/* Update MS IOCB request */
ms_pkt - > req_bytecount =
cpu_to_le32 ( 24 + 1 + ct_req - > req . rsnn_nn . name_len ) ;
ms_pkt - > dseg_req_length = ms_pkt - > req_bytecount ;
/* 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 , 0x2051 ,
" RSNN_NN 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 , " RSNN_NN " ) ! =
2005-07-06 21:30:47 +04:00
QLA_SUCCESS ) {
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 , 0x2052 ,
" RSNN_NN exiting normally. \n " ) ;
2005-04-17 02:20:36 +04:00
}
return ( rval ) ;
}
/**
* qla2x00_prep_sns_cmd ( ) - Prepare common SNS command request fields for query .
* @ ha : HA context
* @ 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 ) ;
return ( sns_cmd ) ;
}
/**
* qla2x00_sns_ga_nxt ( ) - SNS scan for fabric devices via GA_NXT command .
* @ ha : HA context
* @ 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 ,
" GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
2005-04-17 02:20:36 +04:00
" pn %02x%02x%02x%02x%02x%02x%02x%02x "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2005-04-17 02:20:36 +04:00
fcport - > node_name [ 0 ] , fcport - > node_name [ 1 ] ,
fcport - > node_name [ 2 ] , fcport - > node_name [ 3 ] ,
fcport - > node_name [ 4 ] , fcport - > node_name [ 5 ] ,
fcport - > node_name [ 6 ] , fcport - > node_name [ 7 ] ,
fcport - > port_name [ 0 ] , fcport - > port_name [ 1 ] ,
fcport - > port_name [ 2 ] , fcport - > port_name [ 3 ] ,
fcport - > port_name [ 4 ] , fcport - > port_name [ 5 ] ,
fcport - > port_name [ 6 ] , fcport - > port_name [ 7 ] ,
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 .
* @ ha : HA context
* @ 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 .
* @ ha : HA context
* @ 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 " ) ;
ql_dump_buffer ( ql_dbg_disc , vha , 0x207f ,
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 .
* @ ha : HA context
* @ 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 ,
" GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
2005-04-17 02:20:36 +04:00
" pn %02x%02x%02x%02x%02x%02x%02x%02x "
2011-07-14 23:00:13 +04:00
" port_id=%02x%02x%02x. \n " ,
2005-04-17 02:20:36 +04:00
list [ i ] . node_name [ 0 ] , list [ i ] . node_name [ 1 ] ,
list [ i ] . node_name [ 2 ] , list [ i ] . node_name [ 3 ] ,
list [ i ] . node_name [ 4 ] , list [ i ] . node_name [ 5 ] ,
list [ i ] . node_name [ 6 ] , list [ i ] . node_name [ 7 ] ,
list [ i ] . port_name [ 0 ] , list [ i ] . port_name [ 1 ] ,
list [ i ] . port_name [ 2 ] , list [ i ] . port_name [ 3 ] ,
list [ i ] . port_name [ 4 ] , list [ i ] . port_name [ 5 ] ,
list [ i ] . port_name [ 6 ] , list [ i ] . port_name [ 7 ] ,
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 .
* @ ha : HA context
*
* 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 .
* HBA .
* @ ha : HA context
*
* 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 .
2005-08-27 06:08:30 +04:00
* @ ha : HA context
*
* Returns 0 on success .
*/
static 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 .
* @ ha : HA context
* @ 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 ) ;
2005-08-27 06:08:30 +04:00
ms_pkt - > control_flags = __constant_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 ) ;
2005-08-27 06:08:30 +04:00
ms_pkt - > cmd_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
ms_pkt - > total_dsd_count = __constant_cpu_to_le16 ( 2 ) ;
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 .
* @ ha : HA context
* @ 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 ) ;
2005-08-27 06:08:30 +04:00
ct_pkt - > cmd_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
ct_pkt - > rsp_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
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 .
* @ ct_req : CT request buffer
* @ cmd : GS command
* @ rsp_size : response size in bytes
*
* Returns a pointer to the intitialized @ ct_req .
*/
static inline struct ct_sns_req *
qla2x00_prep_ct_fdmi_req ( struct ct_sns_req * ct_req , uint16_t cmd ,
uint16_t rsp_size )
{
memset ( ct_req , 0 , sizeof ( struct ct_sns_pkt ) ) ;
ct_req - > header . revision = 0x01 ;
ct_req - > header . gs_type = 0xFA ;
ct_req - > header . gs_subtype = 0x10 ;
ct_req - > command = cpu_to_be16 ( cmd ) ;
ct_req - > max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
return ct_req ;
}
/**
* qla2x00_fdmi_rhba ( ) -
* @ ha : HA context
*
* 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 ;
uint8_t * entries ;
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 */
ct_req = qla2x00_prep_ct_fdmi_req ( & ha - > ct_sns - > p . req , RHBA_CMD ,
RHBA_RSP_SIZE ) ;
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 ) ;
2005-08-27 06:08:30 +04:00
ct_req - > req . rhba . entry_count = __constant_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 =
__constant_cpu_to_be32 ( FDMI_HBA_ATTR_COUNT ) ;
entries = ct_req - > req . rhba . hba_identifier ;
/* Nodename. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_NODE_NAME ) ;
eiter - > len = __constant_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 ,
" NodeName = %02x%02x%02x%02x%02x%02x%02x%02x. \n " ,
eiter - > a . node_name [ 0 ] , eiter - > a . node_name [ 1 ] ,
eiter - > a . node_name [ 2 ] , eiter - > a . node_name [ 3 ] ,
eiter - > a . node_name [ 4 ] , eiter - > a . node_name [ 5 ] ,
eiter - > a . node_name [ 6 ] , eiter - > a . node_name [ 7 ] ) ;
2005-08-27 06:08:30 +04:00
/* Manufacturer. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_MANUFACTURER ) ;
strcpy ( eiter - > a . manufacturer , " QLogic Corporation " ) ;
alen = strlen ( eiter - > a . manufacturer ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_SERIAL_NUMBER ) ;
sn = ( ( ha - > serial0 & 0x1f ) < < 16 ) | ( ha - > serial2 < < 8 ) | ha - > serial1 ;
sprintf ( eiter - > a . serial_num , " %c%05d " , ' A ' + sn / 100000 , sn % 100000 ) ;
alen = strlen ( eiter - > a . serial_num ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_MODEL ) ;
strcpy ( eiter - > a . model , ha - > model_number ) ;
alen = strlen ( eiter - > a . model ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_MODEL_DESCRIPTION ) ;
if ( ha - > model_desc )
strncpy ( eiter - > a . model_desc , ha - > model_desc , 80 ) ;
alen = strlen ( eiter - > a . model_desc ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_HARDWARE_VERSION ) ;
strcpy ( eiter - > a . hw_version , ha - > adapter_id ) ;
alen = strlen ( eiter - > a . hw_version ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_DRIVER_VERSION ) ;
strcpy ( eiter - > a . driver_version , qla2x00_version_str ) ;
alen = strlen ( eiter - > a . driver_version ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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. */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_OPTION_ROM_VERSION ) ;
strcpy ( eiter - > a . orom_version , " 0.00 " ) ;
alen = strlen ( eiter - > a . orom_version ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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 */
eiter = ( struct ct_fdmi_hba_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_HBA_FIRMWARE_VERSION ) ;
2008-11-06 21:40:19 +03:00
ha - > isp_ops - > fw_version_str ( vha , eiter - > a . fw_version ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . fw_version ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
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 ,
" RHBA identifier = "
" %02x%02x%02x%02x%02x%02x%02x%02x size=%d. \n " ,
ct_req - > req . rhba . hba_identifier [ 0 ] ,
2005-08-27 06:08:30 +04:00
ct_req - > req . rhba . hba_identifier [ 1 ] ,
ct_req - > req . rhba . hba_identifier [ 2 ] ,
ct_req - > req . rhba . hba_identifier [ 3 ] ,
ct_req - > req . rhba . hba_identifier [ 4 ] ,
ct_req - > req . rhba . hba_identifier [ 5 ] ,
ct_req - > req . rhba . hba_identifier [ 6 ] ,
2011-07-14 23:00:13 +04:00
ct_req - > req . rhba . hba_identifier [ 7 ] , size ) ;
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 ;
}
} 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 ;
}
/**
* qla2x00_fdmi_dhba ( ) -
* @ ha : HA context
*
* 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 */
ct_req = qla2x00_prep_ct_fdmi_req ( & ha - > ct_sns - > p . req , DHBA_CMD ,
DHBA_RSP_SIZE ) ;
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 ,
" DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x. \n " ,
2005-08-27 06:08:30 +04:00
ct_req - > req . dhba . port_name [ 0 ] , ct_req - > req . dhba . port_name [ 1 ] ,
ct_req - > req . dhba . port_name [ 2 ] , ct_req - > req . dhba . port_name [ 3 ] ,
ct_req - > req . dhba . port_name [ 4 ] , ct_req - > req . dhba . port_name [ 5 ] ,
2011-07-14 23:00:13 +04:00
ct_req - > req . dhba . port_name [ 6 ] , ct_req - > req . dhba . port_name [ 7 ] ) ;
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 ;
}
/**
* qla2x00_fdmi_rpa ( ) -
* @ ha : HA context
*
* Returns 0 on success .
*/
static int
2008-11-06 21:40:19 +03:00
qla2x00_fdmi_rpa ( scsi_qla_host_t * vha )
2005-08-27 06:08:30 +04:00
{
int rval , alen ;
uint32_t size , max_frame_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 ;
uint8_t * entries ;
struct ct_fdmi_port_attr * eiter ;
struct init_cb_24xx * icb24 = ( struct init_cb_24xx * ) ha - > init_cb ;
/* 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 */
ct_req = qla2x00_prep_ct_fdmi_req ( & ha - > ct_sns - > p . req , RPA_CMD ,
RPA_RSP_SIZE ) ;
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 . rpa . port_name , vha - > port_name , WWN_SIZE ) ;
2005-08-27 06:08:30 +04:00
size = WWN_SIZE + 4 ;
/* Attributes */
ct_req - > req . rpa . attrs . count =
2007-09-21 01:07:41 +04:00
__constant_cpu_to_be32 ( FDMI_PORT_ATTR_COUNT - 1 ) ;
2005-08-27 06:08:30 +04:00
entries = ct_req - > req . rpa . port_name ;
/* FC4 types. */
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_FC4_TYPES ) ;
eiter - > len = __constant_cpu_to_be16 ( 4 + 32 ) ;
eiter - > a . fc4_types [ 2 ] = 0x01 ;
size + = 4 + 32 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2039 ,
" FC4_TYPES=%02x %02x. \n " ,
eiter - > a . fc4_types [ 2 ] ,
eiter - > a . fc4_types [ 1 ] ) ;
2005-08-27 06:08:30 +04:00
/* Supported speed. */
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_SUPPORT_SPEED ) ;
eiter - > len = __constant_cpu_to_be16 ( 4 + 4 ) ;
2012-02-09 23:15:34 +04:00
if ( IS_CNA_CAPABLE ( ha ) )
2009-01-05 22:18:11 +03:00
eiter - > a . sup_speed = __constant_cpu_to_be32 (
FDMI_PORT_SPEED_10GB ) ;
else if ( IS_QLA25XX ( ha ) )
2007-07-20 07:37:34 +04:00
eiter - > a . sup_speed = __constant_cpu_to_be32 (
FDMI_PORT_SPEED_1GB | FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_4GB | FDMI_PORT_SPEED_8GB ) ;
2008-04-04 00:13:26 +04:00
else if ( IS_QLA24XX_TYPE ( ha ) )
2007-07-20 02:05:58 +04:00
eiter - > a . sup_speed = __constant_cpu_to_be32 (
FDMI_PORT_SPEED_1GB | FDMI_PORT_SPEED_2GB |
FDMI_PORT_SPEED_4GB ) ;
2005-08-27 06:08:30 +04:00
else if ( IS_QLA23XX ( ha ) )
2007-07-20 02:05:58 +04:00
eiter - > a . sup_speed = __constant_cpu_to_be32 (
FDMI_PORT_SPEED_1GB | FDMI_PORT_SPEED_2GB ) ;
2005-08-27 06:08:30 +04:00
else
2007-07-20 02:05:58 +04:00
eiter - > a . sup_speed = __constant_cpu_to_be32 (
FDMI_PORT_SPEED_1GB ) ;
2005-08-27 06:08:30 +04:00
size + = 4 + 4 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203a ,
" Supported_Speed=%x. \n " , eiter - > a . sup_speed ) ;
2005-08-27 06:08:30 +04:00
/* Current speed. */
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_CURRENT_SPEED ) ;
eiter - > len = __constant_cpu_to_be16 ( 4 + 4 ) ;
switch ( ha - > link_data_rate ) {
2007-07-20 02:05:58 +04:00
case PORT_SPEED_1GB :
eiter - > a . cur_speed =
__constant_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 :
eiter - > a . cur_speed =
__constant_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 :
eiter - > a . cur_speed =
__constant_cpu_to_be32 ( FDMI_PORT_SPEED_4GB ) ;
break ;
2007-07-20 07:37:34 +04:00
case PORT_SPEED_8GB :
eiter - > a . cur_speed =
__constant_cpu_to_be32 ( FDMI_PORT_SPEED_8GB ) ;
break ;
2009-01-05 22:18:11 +03:00
case PORT_SPEED_10GB :
eiter - > a . cur_speed =
__constant_cpu_to_be32 ( FDMI_PORT_SPEED_10GB ) ;
break ;
2012-02-09 23:15:34 +04:00
case PORT_SPEED_16GB :
eiter - > a . cur_speed =
__constant_cpu_to_be32 ( FDMI_PORT_SPEED_16GB ) ;
break ;
2007-07-20 02:05:58 +04:00
default :
eiter - > a . cur_speed =
__constant_cpu_to_be32 ( FDMI_PORT_SPEED_UNKNOWN ) ;
2005-08-27 06:08:30 +04:00
break ;
}
size + = 4 + 4 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203b ,
" Current_Speed=%x. \n " , eiter - > a . cur_speed ) ;
2005-08-27 06:08:30 +04:00
/* Max frame size. */
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_MAX_FRAME_SIZE ) ;
eiter - > len = __constant_cpu_to_be16 ( 4 + 4 ) ;
2007-07-20 02:05:56 +04:00
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 ) ;
2005-08-27 06:08:30 +04:00
eiter - > a . max_frame_size = cpu_to_be32 ( max_frame_size ) ;
size + = 4 + 4 ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203c ,
" Max_Frame_Size=%x. \n " , eiter - > a . max_frame_size ) ;
2005-08-27 06:08:30 +04:00
/* OS device name. */
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_OS_DEVICE_NAME ) ;
2007-09-21 01:07:41 +04:00
strcpy ( eiter - > a . os_dev_name , QLA2XXX_DRIVER_NAME ) ;
2005-08-27 06:08:30 +04:00
alen = strlen ( eiter - > a . os_dev_name ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x204b ,
" 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. */
2008-11-06 21:40:19 +03:00
if ( strlen ( fc_host_system_hostname ( vha - > host ) ) ) {
2007-09-21 01:07:41 +04:00
ct_req - > req . rpa . attrs . count =
__constant_cpu_to_be32 ( FDMI_PORT_ATTR_COUNT ) ;
2006-10-02 23:00:45 +04:00
eiter = ( struct ct_fdmi_port_attr * ) ( entries + size ) ;
eiter - > type = __constant_cpu_to_be16 ( FDMI_PORT_HOST_NAME ) ;
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
alen = strlen ( eiter - > a . host_name ) ;
alen + = ( alen & 3 ) ? ( 4 - ( alen & 3 ) ) : 4 ;
eiter - > len = cpu_to_be16 ( 4 + alen ) ;
size + = 4 + alen ;
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203d ,
" HostName=%s. \n " , eiter - > a . host_name ) ;
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
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x203e ,
" RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d. \n " ,
ct_req - > req . rpa . port_name [ 0 ] , ct_req - > req . rpa . port_name [ 1 ] ,
ct_req - > req . rpa . port_name [ 2 ] , ct_req - > req . rpa . port_name [ 3 ] ,
ct_req - > req . rpa . port_name [ 4 ] , ct_req - > req . rpa . port_name [ 5 ] ,
ct_req - > req . rpa . port_name [ 6 ] , ct_req - > req . rpa . port_name [ 7 ] ,
size ) ;
ql_dump_buffer ( ql_dbg_disc + ql_dbg_buffer , vha , 0x2079 ,
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 , 0x2040 ,
" RPA 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 ;
} else {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_disc , vha , 0x2041 ,
" RPA exiting nornally. \n " ) ;
2005-08-27 06:08:30 +04:00
}
return rval ;
}
/**
* qla2x00_fdmi_register ( ) -
* @ ha : HA context
*
* 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
{
int rval ;
2009-08-01 02:09:33 +04:00
struct qla_hw_data * ha = vha - > hw ;
if ( IS_QLA2100 ( ha ) | | IS_QLA2200 ( ha ) )
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 ;
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 ) ;
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 .
* @ ha : HA context
* @ 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 ;
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 ;
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 */
2008-11-06 21:40:19 +03:00
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GFPN_ID_REQ_SIZE ,
2006-10-02 23:00:43 +04:00
GFPN_ID_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GFPN_ID_CMD ,
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 void *
2008-11-06 21:40:19 +03:00
qla24xx_prep_ms_fm_iocb ( scsi_qla_host_t * vha , uint32_t req_size ,
2006-10-02 23:00:43 +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 ;
2006-10-02 23:00:43 +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 ) ;
2006-10-02 23:00:43 +04:00
ct_pkt - > cmd_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
ct_pkt - > rsp_dsd_count = __constant_cpu_to_le16 ( 1 ) ;
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 ;
2006-10-02 23:00:43 +04:00
return ct_pkt ;
}
static inline struct ct_sns_req *
qla24xx_prep_ct_fm_req ( struct ct_sns_req * ct_req , uint16_t cmd ,
uint16_t rsp_size )
{
memset ( ct_req , 0 , sizeof ( struct ct_sns_pkt ) ) ;
ct_req - > header . revision = 0x01 ;
ct_req - > header . gs_type = 0xFA ;
ct_req - > header . gs_subtype = 0x01 ;
ct_req - > command = cpu_to_be16 ( cmd ) ;
ct_req - > max_rsp_size = cpu_to_be16 ( ( rsp_size - 16 ) / 4 ) ;
return ct_req ;
}
/**
* qla2x00_gpsc ( ) - FCS Get Port Speed Capabilities ( GPSC ) query .
* @ ha : HA context
* @ 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 ;
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 ;
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 ;
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 */
2008-11-06 21:40:19 +03:00
ms_pkt = qla24xx_prep_ms_fm_iocb ( vha , GPSC_REQ_SIZE ,
2006-10-02 23:00:43 +04:00
GPSC_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla24xx_prep_ct_fm_req ( & ha - > ct_sns - > p . req ,
GPSC_CMD , GPSC_RSP_SIZE ) ;
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 ;
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 "
" %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
" speed=%04x. \n " ,
2006-10-02 23:00:43 +04:00
list [ i ] . fabric_port_name [ 0 ] ,
list [ i ] . fabric_port_name [ 1 ] ,
list [ i ] . fabric_port_name [ 2 ] ,
list [ i ] . fabric_port_name [ 3 ] ,
list [ i ] . fabric_port_name [ 4 ] ,
list [ i ] . fabric_port_name [ 5 ] ,
list [ i ] . fabric_port_name [ 6 ] ,
list [ i ] . fabric_port_name [ 7 ] ,
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 .
*
* @ ha : HA context
* @ 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 ;
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 ;
/* Prepare common MS IOCB */
ms_pkt = ha - > isp_ops - > prep_ms_iocb ( vha , GFF_ID_REQ_SIZE ,
GFF_ID_RSP_SIZE ) ;
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req ( & ha - > ct_sns - > p . req , GFF_ID_CMD ,
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 ;
}
/* Last device exit. */
if ( list [ i ] . d_id . b . rsvd_1 ! = 0 )
break ;
}
}