1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 #ifndef _FCOET_H
  25 #define _FCOET_H
  26 
  27 #include <sys/stmf_defines.h>
  28 
  29 #ifdef  __cplusplus
  30 extern "C" {
  31 #endif
  32 
  33 #ifdef  _KERNEL
  34 
  35 #define FCOET_VERSION   "v20091123-1.02"
  36 #define FCOET_NAME      "COMSTAR FCoET "
  37 #define FCOET_MOD_NAME  FCOET_NAME FCOET_VERSION
  38 
  39 #define FCOET_TASKQ_NAME_LEN    32
  40 
  41 /*
  42  * FCOET logging
  43  */
  44 extern int fcoet_use_ext_log;
  45 
  46 /*
  47  * Caution: 1) LOG will be available in debug/non-debug mode
  48  *          2) Anything which can potentially flood the log should be under
  49  *             extended logging, and use FCOET_EXT_LOG.
  50  *          3) Don't use FCOET_EXT_LOG in performance-critical code path, such
  51  *             as normal SCSI I/O code path. It could hurt system performance.
  52  *          4) Use kmdb to change focet_use_ext_log in the fly to adjust
  53  *             tracing
  54  */
  55 #define FCOET_EXT_LOG(log_ident, ...)   \
  56         {       \
  57                 if (fcoet_use_ext_log) {        \
  58                         fcoe_trace(log_ident, __VA_ARGS__);     \
  59                 }       \
  60         }
  61 
  62 #define FCOET_LOG(log_ident, ...)       \
  63         fcoe_trace(log_ident, __VA_ARGS__)
  64 
  65 /*
  66  * define common-used constants
  67  */
  68 #define FCOET_MAX_LOGINS        2048
  69 #define FCOET_MAX_XCHGES        2048
  70 #define FCOET_SOL_HASH_SIZE     128
  71 #define FCOET_UNSOL_HASH_SIZE   2048
  72 
  73 typedef enum fcoet_sol_flogi_state {
  74         SFS_WAIT_LINKUP = 0,
  75         SFS_FLOGI_INIT,
  76         SFS_FLOGI_CHECK_TIMEOUT,
  77         SFS_ABTS_INIT,
  78         SFS_CLEAR_FLOGI,
  79         SFS_FLOGI_ACC,
  80         SFS_FLOGI_DONE
  81 } fcoet_sol_flogi_state_t;
  82 
  83 /*
  84  * define data structures
  85  */
  86 struct fcoet_exchange;
  87 typedef struct fcoet_soft_state {
  88         /*
  89          * basic information
  90          */
  91         dev_info_t              *ss_dip;
  92         int                      ss_instance;
  93         uint32_t                 ss_flags;
  94         fct_local_port_t        *ss_port;
  95         fcoe_port_t             *ss_eport;
  96         char                     ss_alias[32];
  97         uint32_t                 ss_fcp_data_payload_size;
  98 
  99         /*
 100          * support degregister remote port
 101          */
 102         uint32_t                 ss_rportid_in_dereg;
 103         uint32_t                 ss_rport_dereg_state;
 104 
 105         /*
 106          * oxid/rxid
 107          */
 108         mod_hash_t              *ss_sol_oxid_hash;
 109         mod_hash_t              *ss_unsol_rxid_hash;
 110         uint16_t                 ss_next_sol_oxid;
 111         uint16_t                 ss_next_unsol_rxid;
 112         int                      ss_sol_oxid_hash_empty;
 113         int                      ss_unsol_rxid_hash_empty;
 114 
 115         /*
 116          * watch thread related stuff
 117          */
 118         ddi_taskq_t             *ss_watchdog_taskq;
 119         kcondvar_t               ss_watch_cv;
 120         kmutex_t                 ss_watch_mutex;
 121         uint64_t                 ss_watch_count;
 122         list_t                   ss_abort_xchg_list;
 123 
 124         /*
 125          * topology discovery
 126          */
 127         struct fcoet_exchange   *ss_sol_flogi;
 128         fcoet_sol_flogi_state_t  ss_sol_flogi_state;
 129         fct_link_info_t          ss_link_info;
 130 
 131         /*
 132          * ioctl related stuff
 133          */
 134         uint32_t                 ss_ioctl_flags;
 135         kmutex_t                 ss_ioctl_mutex;
 136 
 137         /*
 138          * special stuff
 139          */
 140         uint32_t                 ss_change_state_flags;
 141         uint8_t                  ss_state:7,
 142             ss_state_not_acked:1;
 143 } fcoet_soft_state_t;
 144 
 145 #define SS_FLAG_UNSOL_FLOGI_DONE        0x0001
 146 #define SS_FLAG_REPORT_TO_FCT           0x0002
 147 #define SS_FLAG_PORT_DISABLED           0x0004
 148 #define SS_FLAG_STOP_WATCH              0x0008
 149 #define SS_FLAG_TERMINATE_WATCHDOG      0x0010
 150 #define SS_FLAG_WATCHDOG_RUNNING        0x0020
 151 #define SS_FLAG_DOG_WAITING             0x0040
 152 #define SS_FLAG_DELAY_PLOGI             0x0080
 153 
 154 /*
 155  * Sequence and frame are transient objects, so their definition is simple.
 156  */
 157 
 158 /*
 159  * Sequence.
 160  * we will not use sequence in current implementation
 161  */
 162 typedef struct fcoet_sequence {
 163         list_t                   seq_frame_list;
 164         struct fcoet_exchange   *seq_exchange;
 165 } fcoet_sequence_t;
 166 
 167 /*
 168  * Frame
 169  */
 170 typedef struct fcoet_frame {
 171         list_node_t              tfm_seq_node;
 172         fcoe_frame_t            *tfm_fcoe_frame;
 173 
 174         struct fcoet_exchange   *tfm_xch;
 175         struct fcoet_sequence   *tfm_seq;
 176         uint8_t                  tfm_rctl;
 177         uint8_t                  tfm_buf_idx;
 178 } fcoet_frame_t;
 179 
 180 /*
 181  * FCOET_MAX_DBUF_LEN should better be consistent with sbd_scsi.c. Since
 182  * sbd_scsi.c use 128k as the max dbuf size, we'd better define this between
 183  * 32k - 128k.
 184  */
 185 #define FCOET_MAX_DBUF_LEN      0x20000 /* 128 * 1024 */
 186 /*
 187  * exchange - cmd alias
 188  */
 189 typedef struct fcoet_exchange {
 190         /*
 191          * it is only used for ss_abort_xchg_list
 192          */
 193         list_node_t              xch_abort_node;
 194 
 195         /*
 196          * We don't believe oxid/rxid in fct_cmd_t
 197          */
 198         uint16_t                 xch_oxid;
 199         uint16_t                 xch_rxid;
 200 
 201         uint32_t                 xch_flags;
 202         fcoet_soft_state_t      *xch_ss;
 203         fct_cmd_t               *xch_cmd;
 204 
 205         fcoet_sequence_t        *xch_current_seq;
 206         clock_t                  xch_start_time;
 207 
 208         stmf_data_buf_t         **xch_dbufs;
 209         uint8_t                 xch_dbuf_num;
 210         uint8_t                 xch_sequence_no;
 211         uint8_t                 xch_ref;
 212 
 213         int                      xch_left_data_size;
 214 } fcoet_exchange_t;
 215 /*
 216  * Add the reference to avoid such situation:
 217  * 1, Frame received, then abort happen (maybe because local port offline, or
 218  * remote port abort the cmd), cmd is aborted and then freed right after we
 219  * get the exchange from hash table in fcoet_rx_frame.
 220  * 2, Frame sent out, then queued in fcoe for release. then abort happen, cmd
 221  * is aborted and then freed before fcoe_watchdog() call up to release the
 222  * frame.
 223  * These two situation should seldom happen. But just invoke this seems won't
 224  * downgrade the performance too much, so we keep it.
 225  */
 226 #define FCOET_BUSY_XCHG(xch)    atomic_add_8(&(xch)->xch_ref, 1)
 227 #define FCOET_RELE_XCHG(xch)    atomic_add_8(&(xch)->xch_ref, -1)
 228 
 229 #define XCH_FLAG_NONFCP_REQ_SENT        0x0001
 230 #define XCH_FLAG_NONFCP_RESP_SENT       0x0002
 231 #define XCH_FLAG_FCP_CMD_RCVD           0x0004
 232 #define XCH_FLAG_INI_ASKED_ABORT        0x0008
 233 #define XCH_FLAG_FCT_CALLED_ABORT       0x0010
 234 #define XCH_FLAG_IN_HASH_TABLE          0x0020
 235 
 236 /*
 237  * IOCTL supporting stuff
 238  */
 239 #define FCOET_IOCTL_FLAG_MASK           0xFF
 240 #define FCOET_IOCTL_FLAG_IDLE           0x00
 241 #define FCOET_IOCTL_FLAG_OPEN           0x01
 242 #define FCOET_IOCTL_FLAG_EXCL           0x02
 243 
 244 /*
 245  * define common-used conversion and calculation macros
 246  */
 247 #define FRM2SS(x_frm)                                                   \
 248         ((fcoet_soft_state_t *)(x_frm)->frm_eport->eport_client_private)
 249 #define FRM2TFM(x_frm)  ((fcoet_frame_t *)(x_frm)->frm_client_private)
 250 
 251 #define PORT2SS(x_port) ((fcoet_soft_state_t *)(x_port)->port_fca_private)
 252 #define EPORT2SS(x_port) ((fcoet_soft_state_t *)(x_port)->eport_client_private)
 253 
 254 #define XCH2ELS(x_xch)  ((fct_els_t *)x_xch->xch_cmd->cmd_specific)
 255 #define XCH2CT(x_xch)   ((fct_ct_t *)x_xch->xch_cmd->cmd_specific)
 256 #define XCH2TASK(x_xch) ((scsi_task_t *)x_xch->xch_cmd->cmd_specific)
 257 
 258 #define CMD2ELS(x_cmd)  ((fct_els_t *)x_cmd->cmd_specific)
 259 #define CMD2CT(x_cmd)   ((fct_sol_ct_t *)x_cmd->cmd_specific)
 260 #define CMD2TASK(x_cmd) ((scsi_task_t *)x_cmd->cmd_specific)
 261 #define CMD2XCH(x_cmd)  ((fcoet_exchange_t *)x_cmd->cmd_fca_private)
 262 #define CMD2SS(x_cmd)                                                   \
 263         ((fcoet_soft_state_t *)(x_cmd)->cmd_port->port_fca_private)
 264 
 265 void fcoet_init_tfm(fcoe_frame_t *frm, fcoet_exchange_t *xch);
 266 fct_status_t fcoet_send_status(fct_cmd_t *cmd);
 267 void fcoet_modhash_find_cb(mod_hash_key_t, mod_hash_val_t);
 268 
 269 /*
 270  * DBUF stuff
 271  */
 272 #define FCOET_DB_SEG_NUM(x_db) (x_db->db_port_private)
 273 #define FCOET_DB_NETB(x_db)                                             \
 274         (((uintptr_t)FCOET_DB_SEG_NUM(x_db)) *                  \
 275         sizeof (struct stmf_sglist_ent) + (uintptr_t)(x_db)->db_sglist)
 276 
 277 #define FCOET_SET_SEG_NUM(x_db, x_num)                  \
 278         {                                               \
 279                 FCOET_DB_SEG_NUM(x_db) = (void *)(unsigned long)x_num;  \
 280         }
 281 
 282 #define FCOET_GET_SEG_NUM(x_db) ((int)(unsigned long)FCOET_DB_SEG_NUM(x_db))
 283 
 284 
 285 #define FCOET_SET_NETB(x_db, x_idx, x_netb)                             \
 286         {                                                               \
 287                 ((void **)FCOET_DB_NETB(x_db))[x_idx] = x_netb; \
 288         }
 289 
 290 #define FCOET_GET_NETB(x_db, x_idx)             \
 291         (((void **)FCOET_DB_NETB(x_db))[x_idx])
 292 
 293 #define PRT_FRM_HDR(x_p, x_f)                                           \
 294         {                                                               \
 295                 FCOET_LOG(x_p, "rctl/%x, type/%x, fctl/%x, oxid/%x",    \
 296                     FCOE_B2V_1((x_f)->frm_hdr->hdr_r_ctl),                \
 297                     FCOE_B2V_1((x_f)->frm_hdr->hdr_type),         \
 298                     FCOE_B2V_3((x_f)->frm_hdr->hdr_f_ctl),                \
 299                     FCOE_B2V_4((x_f)->frm_hdr->hdr_oxid));                \
 300         }
 301 
 302 #endif  /* _KERNEL */
 303 
 304 #ifdef  __cplusplus
 305 }
 306 #endif
 307 
 308 #endif /* _FCOET_H */