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