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