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_inc_8(&(xch)->xch_ref) 227 #define FCOET_RELE_XCHG(xch) atomic_dec_8(&(xch)->xch_ref) 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 FRM_R_CTL(x_f), \ 297 FRM_TYPE(x_f), \ 298 FRM_F_CTL(x_f), \ 299 FRM_OXID(x_f)); \ 300 } 301 302 #endif /* _KERNEL */ 303 304 #ifdef __cplusplus 305 } 306 #endif 307 308 #endif /* _FCOET_H */ 309