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, refers to embedded @u submember
 125 * @sg_rsp: scatterlist entry for response data, refers to embedded @u submember
 126 * @u: request and response specific data
 127 * @u.adisc: ADISC specific data
 128 * @u.adisc.req: ADISC request
 129 * @u.adisc.rsp: ADISC response
 130 * @u.gid_pn: GID_PN specific data
 131 * @u.gid_pn.req: GID_PN request
 132 * @u.gid_pn.rsp: GID_PN response
 133 * @u.gpn_ft: GPN_FT specific data
 134 * @u.gpn_ft.sg_rsp2: GPN_FT response, not embedded here, allocated elsewhere
 135 * @u.gpn_ft.req: GPN_FT request
 136 * @u.gspn: GSPN specific data
 137 * @u.gspn.req: GSPN request
 138 * @u.gspn.rsp: GSPN response
 139 * @u.rspn: RSPN specific data
 140 * @u.rspn.req: RSPN request
 141 * @u.rspn.rsp: RSPN response
 142 */
 143struct zfcp_fc_req {
 144        struct zfcp_fsf_ct_els                          ct_els;
 145        struct scatterlist                              sg_req;
 146        struct scatterlist                              sg_rsp;
 147        union {
 148                struct {
 149                        struct fc_els_adisc             req;
 150                        struct fc_els_adisc             rsp;
 151                } adisc;
 152                struct {
 153                        struct zfcp_fc_gid_pn_req       req;
 154                        struct zfcp_fc_gid_pn_rsp       rsp;
 155                } gid_pn;
 156                struct {
 157                        struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
 158                        struct zfcp_fc_gpn_ft_req       req;
 159                } gpn_ft;
 160                struct {
 161                        struct zfcp_fc_gspn_req         req;
 162                        struct zfcp_fc_gspn_rsp         rsp;
 163                } gspn;
 164                struct {
 165                        struct zfcp_fc_rspn_req         req;
 166                        struct fc_ct_hdr                rsp;
 167                } rspn;
 168        } u;
 169};
 170
 171/**
 172 * enum zfcp_fc_wka_status - FC WKA port status in zfcp
 173 * @ZFCP_FC_WKA_PORT_OFFLINE: Port is closed and not in use
 174 * @ZFCP_FC_WKA_PORT_CLOSING: The FSF "close port" request is pending
 175 * @ZFCP_FC_WKA_PORT_OPENING: The FSF "open port" request is pending
 176 * @ZFCP_FC_WKA_PORT_ONLINE: The port is open and the port handle is valid
 177 */
 178enum zfcp_fc_wka_status {
 179        ZFCP_FC_WKA_PORT_OFFLINE,
 180        ZFCP_FC_WKA_PORT_CLOSING,
 181        ZFCP_FC_WKA_PORT_OPENING,
 182        ZFCP_FC_WKA_PORT_ONLINE,
 183};
 184
 185/**
 186 * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port
 187 * @adapter: Pointer to adapter structure this WKA port belongs to
 188 * @completion_wq: Wait for completion of open/close command
 189 * @status: Current status of WKA port
 190 * @refcount: Reference count to keep port open as long as it is in use
 191 * @d_id: FC destination id or well-known-address
 192 * @handle: FSF handle for the open WKA port
 193 * @mutex: Mutex used during opening/closing state changes
 194 * @work: For delaying the closing of the WKA port
 195 */
 196struct zfcp_fc_wka_port {
 197        struct zfcp_adapter     *adapter;
 198        wait_queue_head_t       completion_wq;
 199        enum zfcp_fc_wka_status status;
 200        atomic_t                refcount;
 201        u32                     d_id;
 202        u32                     handle;
 203        struct mutex            mutex;
 204        struct delayed_work     work;
 205};
 206
 207/**
 208 * struct zfcp_fc_wka_ports - Data structures for FC generic services
 209 * @ms: FC Management service
 210 * @ts: FC time service
 211 * @ds: FC directory service
 212 * @as: FC alias service
 213 */
 214struct zfcp_fc_wka_ports {
 215        struct zfcp_fc_wka_port ms;
 216        struct zfcp_fc_wka_port ts;
 217        struct zfcp_fc_wka_port ds;
 218        struct zfcp_fc_wka_port as;
 219};
 220
 221/**
 222 * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
 223 * @fcp: fcp_cmnd to setup
 224 * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
 225 */
 226static inline
 227void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
 228{
 229        u32 datalen;
 230
 231        int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
 232
 233        fcp->fc_pri_ta = FCP_PTA_SIMPLE;
 234
 235        if (scsi->sc_data_direction == DMA_FROM_DEVICE)
 236                fcp->fc_flags |= FCP_CFL_RDDATA;
 237        if (scsi->sc_data_direction == DMA_TO_DEVICE)
 238                fcp->fc_flags |= FCP_CFL_WRDATA;
 239
 240        memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len);
 241
 242        datalen = scsi_bufflen(scsi);
 243        fcp->fc_dl = cpu_to_be32(datalen);
 244
 245        if (scsi_get_prot_type(scsi) == SCSI_PROT_DIF_TYPE1) {
 246                datalen += datalen / scsi->device->sector_size * 8;
 247                fcp->fc_dl = cpu_to_be32(datalen);
 248        }
 249}
 250
 251/**
 252 * zfcp_fc_fcp_tm() - Setup FCP command as task management command.
 253 * @fcp: Pointer to FCP_CMND IU to set up.
 254 * @dev: Pointer to SCSI_device where to send the task management command.
 255 * @tm_flags: Task management flags to setup tm command.
 256 */
 257static inline
 258void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
 259{
 260        int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
 261        fcp->fc_tm_flags = tm_flags;
 262}
 263
 264/**
 265 * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
 266 * @fcp_rsp: FCP RSP IU to evaluate
 267 * @scsi: SCSI command where to update status and sense buffer
 268 */
 269static inline
 270void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
 271                          struct scsi_cmnd *scsi)
 272{
 273        struct fcp_resp_rsp_info *rsp_info;
 274        char *sense;
 275        u32 sense_len, resid;
 276        u8 rsp_flags;
 277
 278        scsi->result |= fcp_rsp->resp.fr_status;
 279
 280        rsp_flags = fcp_rsp->resp.fr_flags;
 281
 282        if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) {
 283                rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
 284                if (rsp_info->rsp_code == FCP_TMF_CMPL)
 285                        set_host_byte(scsi, DID_OK);
 286                else {
 287                        set_host_byte(scsi, DID_ERROR);
 288                        return;
 289                }
 290        }
 291
 292        if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) {
 293                sense = (char *) &fcp_rsp[1];
 294                if (rsp_flags & FCP_RSP_LEN_VAL)
 295                        sense += be32_to_cpu(fcp_rsp->ext.fr_rsp_len);
 296                sense_len = min_t(u32, be32_to_cpu(fcp_rsp->ext.fr_sns_len),
 297                                  SCSI_SENSE_BUFFERSIZE);
 298                memcpy(scsi->sense_buffer, sense, sense_len);
 299        }
 300
 301        if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
 302                resid = be32_to_cpu(fcp_rsp->ext.fr_resid);
 303                scsi_set_resid(scsi, resid);
 304                if (scsi_bufflen(scsi) - resid < scsi->underflow &&
 305                     !(rsp_flags & FCP_SNS_LEN_VAL) &&
 306                     fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
 307                        set_host_byte(scsi, DID_ERROR);
 308        } else if (unlikely(rsp_flags & FCP_RESID_OVER)) {
 309                /* FCP_DL was not sufficient for SCSI data length */
 310                if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
 311                        set_host_byte(scsi, DID_ERROR);
 312        }
 313}
 314
 315#endif
 316