2009-11-24 18:54:08 +03:00
/*
* zfcp device driver
*
* Fibre Channel related definitions and inline functions for the zfcp
* device driver
*
2012-07-20 13:15:04 +04:00
* Copyright IBM Corp . 2009
2009-11-24 18:54:08 +03:00
*/
# ifndef ZFCP_FC_H
# define ZFCP_FC_H
2009-11-24 18:54:09 +03:00
# include <scsi/fc/fc_els.h>
2009-11-24 18:54:08 +03:00
# include <scsi/fc/fc_fcp.h>
2009-11-24 18:54:10 +03:00
# include <scsi/fc/fc_ns.h>
2009-11-24 18:54:08 +03:00
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_tcq.h>
2009-11-24 18:54:13 +03:00
# include "zfcp_fsf.h"
2009-11-24 18:54:08 +03:00
2009-11-24 18:54:10 +03:00
# define ZFCP_FC_CT_SIZE_PAGE (PAGE_SIZE - sizeof(struct fc_ct_hdr))
# define ZFCP_FC_GPN_FT_ENT_PAGE (ZFCP_FC_CT_SIZE_PAGE \
/ sizeof ( struct fc_gpn_ft_resp ) )
# define ZFCP_FC_GPN_FT_NUM_BUFS 4 /* memory pages */
# define ZFCP_FC_GPN_FT_MAX_SIZE (ZFCP_FC_GPN_FT_NUM_BUFS * PAGE_SIZE \
- sizeof ( struct fc_ct_hdr ) )
# define ZFCP_FC_GPN_FT_MAX_ENT (ZFCP_FC_GPN_FT_NUM_BUFS * \
( ZFCP_FC_GPN_FT_ENT_PAGE + 1 ) )
2010-01-14 19:19:02 +03:00
# define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000)
2010-07-16 17:37:39 +04:00
/**
* struct zfcp_fc_event - FC HBAAPI event for internal queueing from irq context
* @ code : Event code
* @ data : Event data
* @ list : list_head for zfcp_fc_events list
*/
struct zfcp_fc_event {
enum fc_host_event_code code ;
u32 data ;
struct list_head list ;
} ;
/**
* struct zfcp_fc_events - Infrastructure for posting FC events from irq context
* @ list : List for queueing of events from irq context to workqueue
* @ list_lock : Lock for event list
* @ work : work_struct for forwarding events in workqueue
*/
struct zfcp_fc_events {
struct list_head list ;
spinlock_t list_lock ;
struct work_struct work ;
} ;
2009-11-24 18:54:10 +03:00
/**
* struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request
* @ ct_hdr : FC GS common transport header
* @ gid_pn : GID_PN request
*/
struct zfcp_fc_gid_pn_req {
struct fc_ct_hdr ct_hdr ;
struct fc_ns_gid_pn gid_pn ;
} __packed ;
/**
2011-02-22 21:54:42 +03:00
* struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response
2009-11-24 18:54:10 +03:00
* @ ct_hdr : FC GS common transport header
* @ gid_pn : GID_PN response
*/
2011-02-22 21:54:42 +03:00
struct zfcp_fc_gid_pn_rsp {
2009-11-24 18:54:10 +03:00
struct fc_ct_hdr ct_hdr ;
struct fc_gid_pn_resp gid_pn ;
} __packed ;
/**
* struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request
* @ ct_hdr : FC GS common transport header
* @ gpn_ft : GPN_FT request
*/
struct zfcp_fc_gpn_ft_req {
struct fc_ct_hdr ct_hdr ;
struct fc_ns_gid_ft gpn_ft ;
} __packed ;
2011-02-22 21:54:48 +03:00
/**
* struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request
* @ ct_hdr : FC GS common transport header
* @ gspn : GSPN_ID request
*/
struct zfcp_fc_gspn_req {
struct fc_ct_hdr ct_hdr ;
struct fc_gid_pn_resp gspn ;
} __packed ;
/**
* struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response
* @ ct_hdr : FC GS common transport header
* @ gspn : GSPN_ID response
* @ name : The name string of the GSPN_ID response
*/
struct zfcp_fc_gspn_rsp {
struct fc_ct_hdr ct_hdr ;
struct fc_gspn_resp gspn ;
char name [ FC_SYMBOLIC_NAME_SIZE ] ;
} __packed ;
/**
* struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request
* @ ct_hdr : FC GS common transport header
* @ rspn : RSPN_ID request
* @ name : The name string of the RSPN_ID request
*/
struct zfcp_fc_rspn_req {
struct fc_ct_hdr ct_hdr ;
struct fc_ns_rspn rspn ;
char name [ FC_SYMBOLIC_NAME_SIZE ] ;
} __packed ;
2009-11-24 18:54:09 +03:00
/**
2011-02-22 21:54:41 +03:00
* struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp
* @ ct_els : data required for issuing fsf command
* @ sg_req : scatterlist entry for request data
* @ sg_rsp : scatterlist entry for response data
* @ u : request specific data
2009-11-24 18:54:09 +03:00
*/
2011-02-22 21:54:41 +03:00
struct zfcp_fc_req {
struct zfcp_fsf_ct_els ct_els ;
struct scatterlist sg_req ;
struct scatterlist sg_rsp ;
union {
struct {
struct fc_els_adisc req ;
struct fc_els_adisc rsp ;
} adisc ;
2011-02-22 21:54:42 +03:00
struct {
struct zfcp_fc_gid_pn_req req ;
struct zfcp_fc_gid_pn_rsp rsp ;
} gid_pn ;
2011-02-22 21:54:43 +03:00
struct {
struct scatterlist sg_rsp2 [ ZFCP_FC_GPN_FT_NUM_BUFS - 1 ] ;
struct zfcp_fc_gpn_ft_req req ;
} gpn_ft ;
2011-02-22 21:54:48 +03:00
struct {
struct zfcp_fc_gspn_req req ;
struct zfcp_fc_gspn_rsp rsp ;
} gspn ;
struct {
struct zfcp_fc_rspn_req req ;
struct fc_ct_hdr rsp ;
} rspn ;
2011-02-22 21:54:41 +03:00
} u ;
2009-11-24 18:54:09 +03:00
} ;
2009-11-24 18:54:11 +03:00
/**
* enum zfcp_fc_wka_status - FC WKA port status in zfcp
* @ ZFCP_FC_WKA_PORT_OFFLINE : Port is closed and not in use
* @ ZFCP_FC_WKA_PORT_CLOSING : The FSF " close port " request is pending
* @ ZFCP_FC_WKA_PORT_OPENING : The FSF " open port " request is pending
* @ ZFCP_FC_WKA_PORT_ONLINE : The port is open and the port handle is valid
*/
enum zfcp_fc_wka_status {
ZFCP_FC_WKA_PORT_OFFLINE ,
ZFCP_FC_WKA_PORT_CLOSING ,
ZFCP_FC_WKA_PORT_OPENING ,
ZFCP_FC_WKA_PORT_ONLINE ,
} ;
/**
* struct zfcp_fc_wka_port - representation of well - known - address ( WKA ) FC port
* @ adapter : Pointer to adapter structure this WKA port belongs to
* @ completion_wq : Wait for completion of open / close command
* @ status : Current status of WKA port
* @ refcount : Reference count to keep port open as long as it is in use
* @ d_id : FC destination id or well - known - address
* @ handle : FSF handle for the open WKA port
* @ mutex : Mutex used during opening / closing state changes
* @ work : For delaying the closing of the WKA port
*/
struct zfcp_fc_wka_port {
struct zfcp_adapter * adapter ;
wait_queue_head_t completion_wq ;
enum zfcp_fc_wka_status status ;
atomic_t refcount ;
u32 d_id ;
u32 handle ;
struct mutex mutex ;
struct delayed_work work ;
} ;
/**
* struct zfcp_fc_wka_ports - Data structures for FC generic services
* @ ms : FC Management service
* @ ts : FC time service
* @ ds : FC directory service
* @ as : FC alias service
*/
struct zfcp_fc_wka_ports {
struct zfcp_fc_wka_port ms ;
struct zfcp_fc_wka_port ts ;
struct zfcp_fc_wka_port ds ;
struct zfcp_fc_wka_port as ;
} ;
2009-11-24 18:54:08 +03:00
/**
* zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
* @ fcp : fcp_cmnd to setup
* @ scsi : scsi_cmnd where to get LUN , task attributes / flags and CDB
2011-02-22 21:54:45 +03:00
* @ tm : task management flags to setup task management command
2009-11-24 18:54:08 +03:00
*/
static inline
2011-02-22 21:54:45 +03:00
void zfcp_fc_scsi_to_fcp ( struct fcp_cmnd * fcp , struct scsi_cmnd * scsi ,
u8 tm_flags )
2009-11-24 18:54:08 +03:00
{
char tag [ 2 ] ;
int_to_scsilun ( scsi - > device - > lun , ( struct scsi_lun * ) & fcp - > fc_lun ) ;
2011-02-22 21:54:45 +03:00
if ( unlikely ( tm_flags ) ) {
fcp - > fc_tm_flags = tm_flags ;
return ;
}
2009-11-24 18:54:08 +03:00
if ( scsi_populate_tag_msg ( scsi , tag ) ) {
switch ( tag [ 0 ] ) {
case MSG_ORDERED_TAG :
fcp - > fc_pri_ta | = FCP_PTA_ORDERED ;
break ;
case MSG_SIMPLE_TAG :
fcp - > fc_pri_ta | = FCP_PTA_SIMPLE ;
break ;
} ;
} else
fcp - > fc_pri_ta = FCP_PTA_SIMPLE ;
if ( scsi - > sc_data_direction = = DMA_FROM_DEVICE )
fcp - > fc_flags | = FCP_CFL_RDDATA ;
if ( scsi - > sc_data_direction = = DMA_TO_DEVICE )
fcp - > fc_flags | = FCP_CFL_WRDATA ;
memcpy ( fcp - > fc_cdb , scsi - > cmnd , scsi - > cmd_len ) ;
fcp - > fc_dl = scsi_bufflen ( scsi ) ;
2010-07-16 17:37:42 +04:00
if ( scsi_get_prot_type ( scsi ) = = SCSI_PROT_DIF_TYPE1 )
fcp - > fc_dl + = fcp - > fc_dl / scsi - > device - > sector_size * 8 ;
2009-11-24 18:54:08 +03:00
}
/**
* zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
* @ fcp_rsp : FCP RSP IU to evaluate
* @ scsi : SCSI command where to update status and sense buffer
*/
static inline
void zfcp_fc_eval_fcp_rsp ( struct fcp_resp_with_ext * fcp_rsp ,
struct scsi_cmnd * scsi )
{
struct fcp_resp_rsp_info * rsp_info ;
char * sense ;
u32 sense_len , resid ;
u8 rsp_flags ;
set_msg_byte ( scsi , COMMAND_COMPLETE ) ;
scsi - > result | = fcp_rsp - > resp . fr_status ;
rsp_flags = fcp_rsp - > resp . fr_flags ;
if ( unlikely ( rsp_flags & FCP_RSP_LEN_VAL ) ) {
rsp_info = ( struct fcp_resp_rsp_info * ) & fcp_rsp [ 1 ] ;
if ( rsp_info - > rsp_code = = FCP_TMF_CMPL )
set_host_byte ( scsi , DID_OK ) ;
else {
set_host_byte ( scsi , DID_ERROR ) ;
return ;
}
}
if ( unlikely ( rsp_flags & FCP_SNS_LEN_VAL ) ) {
sense = ( char * ) & fcp_rsp [ 1 ] ;
if ( rsp_flags & FCP_RSP_LEN_VAL )
2010-10-05 19:12:55 +04:00
sense + = fcp_rsp - > ext . fr_rsp_len ;
2009-11-24 18:54:08 +03:00
sense_len = min ( fcp_rsp - > ext . fr_sns_len ,
( u32 ) SCSI_SENSE_BUFFERSIZE ) ;
memcpy ( scsi - > sense_buffer , sense , sense_len ) ;
}
if ( unlikely ( rsp_flags & FCP_RESID_UNDER ) ) {
resid = fcp_rsp - > ext . fr_resid ;
scsi_set_resid ( scsi , resid ) ;
if ( scsi_bufflen ( scsi ) - resid < scsi - > underflow & &
! ( rsp_flags & FCP_SNS_LEN_VAL ) & &
fcp_rsp - > resp . fr_status = = SAM_STAT_GOOD )
set_host_byte ( scsi , DID_ERROR ) ;
}
}
# endif