linux-stable/drivers/s390/scsi/zfcp_fc.h
Steffen Maier 9d464fc1b1 scsi: zfcp: use endianness conversions with common FC(P) struct fields
Just to silence sparse. Since zfcp only exists for s390 and
s390 is big endian, this has been working correctly without conversions
and all the new conversions are NOPs so no performance impact.

Nonetheless, use the conversion on the constant expression where possible.

NB: N_Port-IDs have always been handled with hton24 or ntoh24 conversions
because they also convert to / from character array.

Affected common code structs and .fields are:

HOT I/O PATH:
fcp_cmnd .fc_dl
   FCP command: regular SCSI I/O, including DIX case

SEMI-HOT I/O PATH:
fcp_cmnd .fc_dl
   recovery FCP command: task management function (LUN / target reset)
fcp_resp_ext
   FCP response having FCP_SNS_LEN_VAL with .fr_rsp_len .fr_sns_len
   FCP response having FCP_RESID_UNDER with .fr_resid

RECOVERY / DISCOVERY PATHS:
fc_ct_hdr .ct_cmd .ct_mr_size
   zfcp auto port scan [GPN_FT] with fc_gpn_ft_resp.fp_wwpn,
   recovery for returned port [GID_PN] with fc_ns_gid_pn.fn_wwpn,
   get symbolic port name [GSPN],
   register symbolic port name [RSPN] (NPIV only).
fc_els_rscn .rscn_plen
   incoming ELS (RSCN).
fc_els_flogi .fl_wwpn .fl_wwnn
   incoming ELS (PLOGI),
   port open response with .fl_csp.sp_bb_data .fl_cssp[0..3].cp_class,
   FCP channel physical port,
   point-to-point peer (P2P only).
fc_els_logo .fl_n_port_wwn
   incoming ELS (LOGO).
fc_els_adisc .adisc_wwnn .adisc_wwpn
   path test after RSCN for gone target port.

Since v4.10 commit 05de97003c ("linux/types.h: enable endian checks for
all sparse builds"), below sparse endianness reports appear by default.
Previously, one needed to pass argument CF="-D__CHECK_ENDIAN__" to make
as in: $ make C=1 CF="-D__CHECK_ENDIAN__" M=drivers/s390/scsi.

Silenced sparse warnings and one error:

$ make C=1 M=drivers/s390/scsi
...
  CHECK   drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_dbf.c:463:22: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_dbf.c:476:28: warning: restricted __be16 degrades to integer
  CC      drivers/s390/scsi/zfcp_dbf.o
...
  CHECK   drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fc.c:263:26: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:299:41: warning: incorrect type in argument 2 (different base types)
drivers/s390/scsi/zfcp_fc.c:299:41:    expected unsigned long long [unsigned] [usertype] wwpn
drivers/s390/scsi/zfcp_fc.c:299:41:    got restricted __be64 [usertype] fl_wwpn
drivers/s390/scsi/zfcp_fc.c:309:40: warning: incorrect type in argument 2 (different base types)
drivers/s390/scsi/zfcp_fc.c:309:40:    expected unsigned long long [unsigned] [usertype] wwpn
drivers/s390/scsi/zfcp_fc.c:309:40:    got restricted __be64 [usertype] fl_n_port_wwn
drivers/s390/scsi/zfcp_fc.c:338:31: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:355:24: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:355:24:    expected restricted __be16 [usertype] ct_cmd
drivers/s390/scsi/zfcp_fc.c:355:24:    got unsigned short [unsigned] [usertype] cmd
drivers/s390/scsi/zfcp_fc.c:356:28: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:356:28:    expected restricted __be16 [usertype] ct_mr_size
drivers/s390/scsi/zfcp_fc.c:356:28:    got int
drivers/s390/scsi/zfcp_fc.c:379:36: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:379:36:    expected restricted __be64 [usertype] fn_wwpn
drivers/s390/scsi/zfcp_fc.c:379:36:    got unsigned long long [unsigned] [usertype] wwpn
drivers/s390/scsi/zfcp_fc.c:463:18: warning: restricted __be64 degrades to integer
drivers/s390/scsi/zfcp_fc.c:465:17: warning: cast from restricted __be64
drivers/s390/scsi/zfcp_fc.c:473:20: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:473:20:    expected unsigned long long [unsigned] [usertype] wwnn
drivers/s390/scsi/zfcp_fc.c:473:20:    got restricted __be64 [usertype] fl_wwnn
drivers/s390/scsi/zfcp_fc.c:474:29: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:474:29:    expected unsigned int [unsigned] [usertype] maxframe_size
drivers/s390/scsi/zfcp_fc.c:474:29:    got restricted __be16 [usertype] sp_bb_data
drivers/s390/scsi/zfcp_fc.c:476:30: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:478:30: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:480:30: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:482:30: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:500:28: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:500:28:    expected unsigned long long [unsigned] [usertype] wwnn
drivers/s390/scsi/zfcp_fc.c:500:28:    got restricted __be64 [usertype] adisc_wwnn
drivers/s390/scsi/zfcp_fc.c:502:38: warning: restricted __be64 degrades to integer
drivers/s390/scsi/zfcp_fc.c:541:40: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:541:40:    expected restricted __be64 [usertype] adisc_wwpn
drivers/s390/scsi/zfcp_fc.c:541:40:    got unsigned long long [unsigned] [usertype] port_name
drivers/s390/scsi/zfcp_fc.c:542:40: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fc.c:542:40:    expected restricted __be64 [usertype] adisc_wwnn
drivers/s390/scsi/zfcp_fc.c:542:40:    got unsigned long long [unsigned] [usertype] node_name
drivers/s390/scsi/zfcp_fc.c:669:16: warning: restricted __be16 degrades to integer
drivers/s390/scsi/zfcp_fc.c:696:24: warning: restricted __be64 degrades to integer
drivers/s390/scsi/zfcp_fc.c:699:54: warning: incorrect type in argument 2 (different base types)
drivers/s390/scsi/zfcp_fc.c:699:54:    expected unsigned long long [unsigned] [usertype] <noident>
drivers/s390/scsi/zfcp_fc.c:699:54:    got restricted __be64 [usertype] fp_wwpn
  CC      drivers/s390/scsi/zfcp_fc.o
  CHECK   drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.c:479:34: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fsf.c:479:34:    expected unsigned long long [unsigned] [usertype] port_name
drivers/s390/scsi/zfcp_fsf.c:479:34:    got restricted __be64 [usertype] fl_wwpn
drivers/s390/scsi/zfcp_fsf.c:480:34: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fsf.c:480:34:    expected unsigned long long [unsigned] [usertype] node_name
drivers/s390/scsi/zfcp_fsf.c:480:34:    got restricted __be64 [usertype] fl_wwnn
drivers/s390/scsi/zfcp_fsf.c:506:36: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fsf.c:506:36:    expected unsigned long long [unsigned] [usertype] peer_wwpn
drivers/s390/scsi/zfcp_fsf.c:506:36:    got restricted __be64 [usertype] fl_wwpn
drivers/s390/scsi/zfcp_fsf.c:507:36: warning: incorrect type in assignment (different base types)
drivers/s390/scsi/zfcp_fsf.c:507:36:    expected unsigned long long [unsigned] [usertype] peer_wwnn
drivers/s390/scsi/zfcp_fsf.c:507:36:    got restricted __be64 [usertype] fl_wwnn
drivers/s390/scsi/zfcp_fc.h:269:46: warning: restricted __be32 degrades to integer
drivers/s390/scsi/zfcp_fc.h:270:29: error: incompatible types in comparison expression (different base types)

Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.vnet.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.vnet.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2017-08-10 19:37:00 -04:00

294 lines
7.8 KiB
C

/*
* zfcp device driver
*
* Fibre Channel related definitions and inline functions for the zfcp
* device driver
*
* Copyright IBM Corp. 2009, 2017
*/
#ifndef ZFCP_FC_H
#define ZFCP_FC_H
#include <scsi/fc/fc_els.h>
#include <scsi/fc/fc_fcp.h>
#include <scsi/fc/fc_ns.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
#include "zfcp_fsf.h"
#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))
#define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000)
/**
* 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;
};
/**
* 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;
/**
* struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response
* @ct_hdr: FC GS common transport header
* @gid_pn: GID_PN response
*/
struct zfcp_fc_gid_pn_rsp {
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;
/**
* 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;
/**
* 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
*/
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;
struct {
struct zfcp_fc_gid_pn_req req;
struct zfcp_fc_gid_pn_rsp rsp;
} gid_pn;
struct {
struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
struct zfcp_fc_gpn_ft_req req;
} gpn_ft;
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;
} u;
};
/**
* 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;
};
/**
* 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
* @tm: task management flags to setup task management command
*/
static inline
void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
u8 tm_flags)
{
u32 datalen;
int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
if (unlikely(tm_flags)) {
fcp->fc_tm_flags = tm_flags;
return;
}
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);
datalen = scsi_bufflen(scsi);
fcp->fc_dl = cpu_to_be32(datalen);
if (scsi_get_prot_type(scsi) == SCSI_PROT_DIF_TYPE1) {
datalen += datalen / scsi->device->sector_size * 8;
fcp->fc_dl = cpu_to_be32(datalen);
}
}
/**
* 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)
sense += be32_to_cpu(fcp_rsp->ext.fr_rsp_len);
sense_len = min_t(u32, be32_to_cpu(fcp_rsp->ext.fr_sns_len),
SCSI_SENSE_BUFFERSIZE);
memcpy(scsi->sense_buffer, sense, sense_len);
}
if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
resid = be32_to_cpu(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);
} else if (unlikely(rsp_flags & FCP_RESID_OVER)) {
/* FCP_DL was not sufficient for SCSI data length */
if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
set_host_byte(scsi, DID_ERROR);
}
}
#endif