linux/drivers/s390/scsi/zfcp_fc.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * zfcp device driver
   4 *
   5 * Fibre Channel related definitions and inline functions for the zfcp
   6 * device driver
   7 *
   8 * Copyright IBM Corp. 2009, 2017
   9 */
  10
  11#ifndef ZFCP_FC_H
  12#define ZFCP_FC_H
  13
  14#include <scsi/fc/fc_els.h>
  15#include <scsi/fc/fc_fcp.h>
  16#include <scsi/fc/fc_ns.h>
  17#include <scsi/scsi_cmnd.h>
  18#include <scsi/scsi_tcq.h>
  19#include "zfcp_fsf.h"
  20
  21#define ZFCP_FC_CT_SIZE_PAGE      (PAGE_SIZE - sizeof(struct fc_ct_hdr))
  22#define ZFCP_FC_GPN_FT_ENT_PAGE   (ZFCP_FC_CT_SIZE_PAGE \
  23                                        / sizeof(struct fc_gpn_ft_resp))
  24#define ZFCP_FC_GPN_FT_NUM_BUFS   4 /* memory pages */
  25
  26#define ZFCP_FC_GPN_FT_MAX_SIZE   (ZFCP_FC_GPN_FT_NUM_BUFS * PAGE_SIZE \
  27                                        - sizeof(struct fc_ct_hdr))
  28#define ZFCP_FC_GPN_FT_MAX_ENT    (ZFCP_FC_GPN_FT_NUM_BUFS * \
  29                                        (ZFCP_FC_GPN_FT_ENT_PAGE + 1))
  30
  31#define ZFCP_FC_CTELS_TMO       (2 * FC_DEF_R_A_TOV / 1000)
  32
  33/**
  34 * struct zfcp_fc_event - FC HBAAPI event for internal queueing from irq context
  35 * @code: Event code
  36 * @data: Event data
  37 * @list: list_head for zfcp_fc_events list
  38 */
  39struct zfcp_fc_event {
  40        enum fc_host_event_code code;
  41        u32 data;
  42        struct list_head list;
  43};
  44
  45/**
  46 * struct zfcp_fc_events - Infrastructure for posting FC events from irq context
  47 * @list: List for queueing of events from irq context to workqueue
  48 * @list_lock: Lock for event list
  49 * @work: work_struct for forwarding events in workqueue
  50*/
  51struct zfcp_fc_events {
  52        struct list_head list;
  53        spinlock_t list_lock;
  54        struct work_struct work;
  55};
  56
  57/**
  58 * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request
  59 * @ct_hdr: FC GS common transport header
  60 * @gid_pn: GID_PN request
  61 */
  62struct zfcp_fc_gid_pn_req {
  63        struct fc_ct_hdr        ct_hdr;
  64        struct fc_ns_gid_pn     gid_pn;
  65} __packed;
  66
  67/**
  68 * struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response
  69 * @ct_hdr: FC GS common transport header
  70 * @gid_pn: GID_PN response
  71 */
  72struct zfcp_fc_gid_pn_rsp {
  73        struct fc_ct_hdr        ct_hdr;
  74        struct fc_gid_pn_resp   gid_pn;
  75} __packed;
  76
  77/**
  78 * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request
  79 * @ct_hdr: FC GS common transport header
  80 * @gpn_ft: GPN_FT request
  81 */
  82struct zfcp_fc_gpn_ft_req {
  83        struct fc_ct_hdr        ct_hdr;
  84        struct fc_ns_gid_ft     gpn_ft;
  85} __packed;
  86
  87/**
  88 * struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request
  89 * @ct_hdr: FC GS common transport header
  90 * @gspn: GSPN_ID request
  91 */
  92struct zfcp_fc_gspn_req {
  93        struct fc_ct_hdr        ct_hdr;
  94        struct fc_gid_pn_resp   gspn;
  95} __packed;
  96
  97/**
  98 * struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response
  99 * @ct_hdr: FC GS common transport header
 100 * @gspn: GSPN_ID response
 101 * @name: The name string of the GSPN_ID response
 102 */
 103struct zfcp_fc_gspn_rsp {
 104        struct fc_ct_hdr        ct_hdr;
 105        struct fc_gspn_resp     gspn;
 106        char                    name[FC_SYMBOLIC_NAME_SIZE];
 107} __packed;
 108
 109/**
 110 * struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request
 111 * @ct_hdr: FC GS common transport header
 112 * @rspn: RSPN_ID request
 113 * @name: The name string of the RSPN_ID request
 114 */
 115struct zfcp_fc_rspn_req {
 116        struct fc_ct_hdr        ct_hdr;
 117        struct fc_ns_rspn       rspn;
 118        char                    name[FC_SYMBOLIC_NAME_SIZE];
 119} __packed;
 120
 121/**
 122 * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp
 123 * @ct_els: data required for issuing fsf command
 124 * @sg_req: scatterlist entry for request data
 125 * @sg_rsp: scatterlist entry for response data
 126 * @u: request specific data
 127 */
 128struct zfcp_fc_req {
 129        struct zfcp_fsf_ct_els                          ct_els;
 130        struct scatterlist                              sg_req;
 131        struct scatterlist                              sg_rsp;
 132        union {
 133                struct {
 134                        struct fc_els_adisc             req;
 135                        struct fc_els_adisc             rsp;
 136                } adisc;
 137                struct {
 138                        struct zfcp_fc_gid_pn_req       req;
 139                        struct zfcp_fc_gid_pn_rsp       rsp;
 140                } gid_pn;
 141                struct {
 142                        struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
 143                        struct zfcp_fc_gpn_ft_req       req;
 144                } gpn_ft;
 145                struct {
 146                        struct zfcp_fc_gspn_req         req;
 147                        struct zfcp_fc_gspn_rsp         rsp;
 148                } gspn;
 149                struct {
 150                        struct zfcp_fc_rspn_req         req;
 151                        struct fc_ct_hdr                rsp;
 152                } rspn;
 153        } u;
 154};
 155
 156/**
 157 * enum zfcp_fc_wka_status - FC WKA port status in zfcp
 158 * @ZFCP_FC_WKA_PORT_OFFLINE: Port is closed and not in use
 159 * @ZFCP_FC_WKA_PORT_CLOSING: The FSF "close port" request is pending
 160 * @ZFCP_FC_WKA_PORT_OPENING: The FSF "open port" request is pending
 161 * @ZFCP_FC_WKA_PORT_ONLINE: The port is open and the port handle is valid
 162 */
 163enum zfcp_fc_wka_status {
 164        ZFCP_FC_WKA_PORT_OFFLINE,
 165        ZFCP_FC_WKA_PORT_CLOSING,
 166        ZFCP_FC_WKA_PORT_OPENING,
 167        ZFCP_FC_WKA_PORT_ONLINE,
 168};
 169
 170/**
 171 * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port
 172 * @adapter: Pointer to adapter structure this WKA port belongs to
 173 * @completion_wq: Wait for completion of open/close command
 174 * @status: Current status of WKA port
 175 * @refcount: Reference count to keep port open as long as it is in use
 176 * @d_id: FC destination id or well-known-address
 177 * @handle: FSF handle for the open WKA port
 178 * @mutex: Mutex used during opening/closing state changes
 179 * @work: For delaying the closing of the WKA port
 180 */
 181struct zfcp_fc_wka_port {
 182        struct zfcp_adapter     *adapter;
 183        wait_queue_head_t       completion_wq;
 184        enum zfcp_fc_wka_status status;
 185        atomic_t                refcount;
 186        u32                     d_id;
 187        u32                     handle;
 188        struct mutex            mutex;
 189        struct delayed_work     work;
 190};
 191
 192/**
 193 * struct zfcp_fc_wka_ports - Data structures for FC generic services
 194 * @ms: FC Management service
 195 * @ts: FC time service
 196 * @ds: FC directory service
 197 * @as: FC alias service
 198 */
 199struct zfcp_fc_wka_ports {
 200        struct zfcp_fc_wka_port ms;
 201        struct zfcp_fc_wka_port ts;
 202        struct zfcp_fc_wka_port ds;
 203        struct zfcp_fc_wka_port as;
 204};
 205
 206/**
 207 * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
 208 * @fcp: fcp_cmnd to setup
 209 * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
 210 */
 211static inline
 212void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
 213{
 214        u32 datalen;
 215
 216        int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
 217
 218        fcp->fc_pri_ta = FCP_PTA_SIMPLE;
 219
 220        if (scsi->sc_data_direction == DMA_FROM_DEVICE)
 221                fcp->fc_flags |= FCP_CFL_RDDATA;
 222        if (scsi->sc_data_direction == DMA_TO_DEVICE)
 223                fcp->fc_flags |= FCP_CFL_WRDATA;
 224
 225        memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len);
 226
 227        datalen = scsi_bufflen(scsi);
 228        fcp->fc_dl = cpu_to_be32(datalen);
 229
 230        if (scsi_get_prot_type(scsi) == SCSI_PROT_DIF_TYPE1) {
 231                datalen += datalen / scsi->device->sector_size * 8;
 232                fcp->fc_dl = cpu_to_be32(datalen);
 233        }
 234}
 235
 236/**
 237 * zfcp_fc_fcp_tm() - Setup FCP command as task management command.
 238 * @fcp: Pointer to FCP_CMND IU to set up.
 239 * @dev: Pointer to SCSI_device where to send the task management command.
 240 * @tm_flags: Task management flags to setup tm command.
 241 */
 242static inline
 243void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
 244{
 245        int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
 246        fcp->fc_tm_flags = tm_flags;
 247}
 248
 249/**
 250 * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
 251 * @fcp_rsp: FCP RSP IU to evaluate
 252 * @scsi: SCSI command where to update status and sense buffer
 253 */
 254static inline
 255void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
 256                          struct scsi_cmnd *scsi)
 257{
 258        struct fcp_resp_rsp_info *rsp_info;
 259        char *sense;
 260        u32 sense_len, resid;
 261        u8 rsp_flags;
 262
 263        set_msg_byte(scsi, COMMAND_COMPLETE);
 264        scsi->result |= fcp_rsp->resp.fr_status;
 265
 266        rsp_flags = fcp_rsp->resp.fr_flags;
 267
 268        if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) {
 269                rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
 270                if (rsp_info->rsp_code == FCP_TMF_CMPL)
 271                        set_host_byte(scsi, DID_OK);
 272                else {
 273                        set_host_byte(scsi, DID_ERROR);
 274                        return;
 275                }
 276        }
 277
 278        if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) {
 279                sense = (char *) &fcp_rsp[1];
 280                if (rsp_flags & FCP_RSP_LEN_VAL)
 281                        sense += be32_to_cpu(fcp_rsp->ext.fr_rsp_len);
 282                sense_len = min_t(u32, be32_to_cpu(fcp_rsp->ext.fr_sns_len),
 283                                  SCSI_SENSE_BUFFERSIZE);
 284                memcpy(scsi->sense_buffer, sense, sense_len);
 285        }
 286
 287        if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
 288                resid = be32_to_cpu(fcp_rsp->ext.fr_resid);
 289                scsi_set_resid(scsi, resid);
 290                if (scsi_bufflen(scsi) - resid < scsi->underflow &&
 291                     !(rsp_flags & FCP_SNS_LEN_VAL) &&
 292                     fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
 293                        set_host_byte(scsi, DID_ERROR);
 294        } else if (unlikely(rsp_flags & FCP_RESID_OVER)) {
 295                /* FCP_DL was not sufficient for SCSI data length */
 296                if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
 297                        set_host_byte(scsi, DID_ERROR);
 298        }
 299}
 300
 301#endif
 302