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 _FCT_IMPL_H 26 #define _FCT_IMPL_H 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #define RSCN_OPTION_VERIFY 0x0001 33 34 typedef enum fct_li_state { 35 LI_STATE_DO_FLOGI = 0, /* FLOGI handled by FCA */ 36 LI_STATE_FINI_TOPOLOGY, /* Finalize topology */ 37 LI_STATE_N2N_PLOGI, /* In case of a N2N connection */ 38 39 LI_STATE_DO_FCLOGIN, /* Login into 0xFFFFFD */ 40 LI_STATE_DO_SCR, /* State change registration */ 41 42 LI_STATE_DO_NSLOGIN, /* Login into 0xFFFFFC */ 43 LI_STATE_DO_RNN, /* Register node name */ 44 LI_STATE_DO_RCS, /* Register classes of service */ 45 LI_STATE_DO_RFT, /* Register FC-4 types */ 46 LI_STATE_DO_RSPN, /* Register symbolic port name */ 47 LI_STATE_DO_RSNN, /* Register symbolic node name */ 48 49 LI_STATE_MAX /* Not a real state */ 50 } fct_li_state_t; 51 52 #define LI_STATE_START 0 53 #define LI_STATE_MASK 0x3F 54 /* Next state depends on the return value */ 55 #define LI_STATE_FLAG_CMD_RETCHECK 0x40 56 /* Link init cmd is still outstanding */ 57 #define LI_STATE_FLAG_CMD_WAITING 0x80 58 /* Flag to indicate that link info is not available yet */ 59 #define LI_STATE_FLAG_NO_LI_YET 0x100 60 61 #define FCT_MAX_CACHED_CMDS 256 62 #define USEC_ELS_TIMEOUT (10 * 1000 * 1000) 63 #define USEC_SOL_TIMEOUT (10 * 1000 * 1000) 64 #define USEC_DEREG_RP_TIMEOUT (25 * 1000 * 1000) 65 #define USEC_DEREG_RP_INTERVAL (2 * 1000 * 1000) 66 67 struct fct_i_cmd; 68 typedef void (* fct_icmd_cb_t)(struct fct_i_cmd *icmd); 69 typedef struct fct_i_cmd { 70 fct_cmd_t *icmd_cmd; 71 uint32_t icmd_alloc_size; 72 fct_struct_id_t icmd_struct_id; 73 uint32_t icmd_flags; 74 clock_t icmd_start_time; 75 struct fct_i_cmd *icmd_next; /* iport_abort_queue and irp */ 76 struct fct_i_cmd *icmd_solcmd_next; /* iport_solcmd_queue */ 77 fct_icmd_cb_t icmd_cb; 78 void *icmd_cb_private; 79 } fct_i_cmd_t; 80 81 /* 82 * icmd_flags 83 */ 84 #define ICMD_SESSION_AFFECTING 0x0002 85 #define ICMD_IN_IRP_QUEUE 0x0004 86 #define ICMD_BEING_ABORTED 0x0008 87 #define ICMD_KNOWN_TO_FCA 0x0020 88 #define ICMD_FCA_ABORT_CALLED 0x0040 89 #define ICMD_CMD_COMPLETE 0x0080 90 #define ICMD_IN_TRANSITION 0x0100 91 #define ICMD_ABTS_RECEIVED 0x0200 92 #define ICMD_IMPLICIT 0x0400 93 #define ICMD_IMPLICIT_CMD_HAS_RESOURCE 0x0800 94 /* High order are debug flags */ 95 #define ICMD_ELS_PROCESSING_STARTED 0x80000000 96 97 /* 98 * For solicited commands, there's only 3 states: 99 * 1) it's new. We need send it to FCA. ICMD_SOLCMD_NEW is set 100 * 2) it's running. We are waiting for completion. 101 * 3) it's completed. We need free it. ICMD_CMD_COMPLETE is set 102 * ICMD_SOLCMD_NEW and ICMD_CMD_COMPLETE should not be set in the same time 103 */ 104 #define ICMD_IN_SOLCMD_QUEUE 0x010000 105 #define ICMD_SOLCMD_NEW 0x020000 106 107 typedef struct fct_i_remote_port { 108 fct_remote_port_t *irp_rp; 109 uint32_t irp_alloc_size; 110 fct_struct_id_t irp_struct_id; 111 krwlock_t irp_lock; 112 113 /* For queueing to local port */ 114 struct fct_i_remote_port *irp_next; 115 116 /* For queueing to handle elses */ 117 struct fct_i_remote_port *irp_discovery_next; 118 119 fct_i_cmd_t *irp_els_list; 120 121 /* 122 * sa stands for session affecting, nsa is non session affecting. 123 * The els counts only represent elses under progress not the ones 124 * that are terminated. active_xchg_count covers everything including 125 * the ones waiting to be terminated. 126 */ 127 uint16_t irp_sa_elses_count; 128 uint16_t irp_nsa_elses_count; 129 uint16_t irp_fcp_xchg_count; 130 uint16_t irp_nonfcp_xchg_count; 131 132 uint32_t irp_flags; 133 clock_t irp_deregister_timer; 134 uint32_t irp_dereg_count; 135 136 uint32_t irp_portid; 137 uint8_t irp_id[24]; 138 uint32_t irp_rcvd_prli_params; 139 uint32_t irp_sent_prli_params; 140 141 /* 142 * Most HBAs will only register symbolic node name instead of port name, 143 * so we use SNN as session alias. 144 */ 145 stmf_scsi_session_t *irp_session; 146 char *irp_snn; 147 148 /* items will be filled in ns cmd */ 149 uint8_t irp_fc4types[32]; /* FC-4 types */ 150 char *irp_spn; /* port symbolic name */ 151 uint32_t irp_cos; /* class of service */ 152 153 uint32_t irp_rscn_counter; 154 } fct_i_remote_port_t; 155 156 /* 157 * structure used for fct_rls_cb() callback private data 158 */ 159 typedef struct fct_rls_cb_data { 160 struct fct_port_link_status *fct_link_status; 161 fct_status_t fct_els_res; 162 } fct_rls_cb_data_t; 163 164 /* 165 * irp flags 166 */ 167 #define IRP_PLOGI_DONE 0x0001 168 #define IRP_PRLI_DONE 0x0002 169 #define IRP_IN_DISCOVERY_QUEUE 0x0004 170 #define IRP_FCP_CLEANUP 0x0008 171 #define IRP_SESSION_CLEANUP (IRP_FCP_CLEANUP | 0x0010) 172 #define IRP_HANDLE_OPENED 0x0020 173 #define IRP_SCSI_SESSION_STARTED 0x0040 174 #define IRP_RSCN_QUEUED 0x0080 175 #define IRP_SOL_PLOGI_IN_PROGRESS 0x0100 176 177 typedef struct fct_cmd_slot { 178 fct_i_cmd_t *slot_cmd; 179 uint16_t slot_no; 180 uint16_t slot_next; 181 uint8_t slot_uniq_cntr; 182 } fct_cmd_slot_t; 183 #define FCT_SLOT_EOL 0xffff 184 185 #define FCT_HASH_TABLE_SIZE 256 186 #define FCT_LOOP_HASH(portid) (portid & 0xff) 187 #define FCT_FABRIC_HASH(portid) (((portid & 0x1f00) | \ 188 ((portid & 0x70000)>>3)) >> 8) 189 #define FCT_PORTID_HASH_FUNC(portid) \ 190 ((portid & 0xFFFF00)?FCT_FABRIC_HASH(portid):FCT_LOOP_HASH(portid)) 191 192 typedef struct fct_i_local_port { 193 fct_local_port_t *iport_port; 194 uint32_t iport_alloc_size; 195 fct_struct_id_t iport_struct_id; 196 197 struct fct_i_local_port *iport_next; 198 struct fct_i_local_port *iport_prev; 199 200 char *iport_alias; 201 char iport_alias_mem[16]; 202 uint8_t iport_id[24]; /* scsi_devid_desc_t */ 203 krwlock_t iport_lock; 204 uint32_t iport_flags; 205 uint16_t iport_link_state; 206 uint8_t iport_state:7, 207 iport_state_not_acked:1; 208 uint8_t iport_offline_prstate; 209 struct fct_link_info iport_link_info; 210 211 fct_i_remote_port_t **iport_rp_slots; 212 fct_i_remote_port_t **iport_rp_tb; 213 uint32_t iport_nrps_login; /* currently logged in */ 214 uint32_t iport_nrps; /* items in hash table */ 215 uint64_t iport_last_change; 216 217 /* 218 * These variables are used to manage fct_cmd_t cache for SCSI traffic 219 */ 220 /* 221 * Total # of cmds allocated by the driver. Some of which are free 222 * and sitting on iport_cached_cmdlist. And some are executing. 223 */ 224 uint32_t iport_total_alloced_ncmds; 225 226 /* 227 * Max active cmds in last interval (10 or 30 seconds) 228 */ 229 uint32_t iport_max_active_ncmds; 230 231 /* 232 * # of free cmds sitting on the iport_cached_cmdlist 233 */ 234 uint32_t iport_cached_ncmds; 235 struct fct_i_cmd *iport_cached_cmdlist; 236 kmutex_t iport_cached_cmd_lock; 237 238 /* 239 * To release free cmds periodically 240 */ 241 clock_t iport_cmdcheck_clock; 242 243 uint16_t iport_task_green_limit; 244 uint16_t iport_task_yellow_limit; 245 uint16_t iport_task_red_limit; 246 /* cmd slots */ 247 uint16_t iport_nslots_free; 248 249 /* upper 16 bits is just a counter to avoid ABA issues */ 250 uint32_t iport_next_free_slot; 251 252 uint8_t iport_login_retry; /* for flogi and N2N plogi */ 253 uint8_t iport_link_old_topology; 254 uint8_t iport_link_cleanup_retry; 255 clock_t iport_li_cmd_timeout; /* for li state m/c */ 256 fct_cmd_slot_t *iport_cmd_slots; 257 258 /* worker thread data */ 259 ddi_taskq_t *iport_worker_taskq; 260 kmutex_t iport_worker_lock; 261 kcondvar_t iport_worker_cv; 262 struct fct_i_event *iport_event_head; 263 struct fct_i_event *iport_event_tail; 264 struct fct_i_cmd *iport_abort_queue; 265 struct fct_i_cmd **iport_ppicmd_term; 266 267 /* link initialization */ 268 fct_status_t iport_li_comp_status; 269 enum fct_li_state iport_li_state; 270 271 /* solicited cmd link */ 272 struct fct_i_cmd *iport_solcmd_queue; 273 274 /* rpwe = remote port with pending els(es) */ 275 fct_i_remote_port_t *iport_rpwe_head; 276 fct_i_remote_port_t *iport_rpwe_tail; 277 kstat_t *iport_kstat_portstat; 278 ksema_t iport_rls_sema; 279 fct_rls_cb_data_t iport_rls_cb_data; 280 } fct_i_local_port_t; 281 282 #define IPORT_FLOGI_DONE(iport) PORT_FLOGI_DONE(&(iport)->iport_link_info) 283 284 /* 285 * iport flags 286 */ 287 #define IPORT_WORKER_RUNNING 0x0001 288 #define IPORT_TERMINATE_WORKER 0x0002 289 #define IPORT_WORKER_DOING_TIMEDWAIT 0x0004 290 #define IPORT_WORKER_DOING_WAIT 0x0008 291 #define IPORT_FLAG_PORT_OFFLINED 0x0010 292 #define IPORT_ALLOW_UNSOL_FLOGI 0x0020 293 294 #define IS_WORKER_SLEEPING(iport) ((iport)->iport_flags & \ 295 (IPORT_WORKER_DOING_TIMEDWAIT | IPORT_WORKER_DOING_WAIT)) 296 297 /* Limits for scsi task load of local port */ 298 #define FCT_TASK_GREEN_LIMIT 80 299 #define FCT_TASK_YELLOW_LIMIT 90 300 #define FCT_TASK_RED_LIMIT 95 301 302 typedef struct fct_i_event { 303 struct fct_i_event *event_next; 304 int event_type; 305 } fct_i_event_t; 306 307 typedef enum { /* Seggested action values for discovery thread */ 308 DISC_ACTION_NO_WORK = 0, 309 DISC_ACTION_RESCAN = 1, 310 DISC_ACTION_DELAY_RESCAN = 2, 311 DISC_ACTION_USE_SHORT_DELAY = 4 312 } disc_action_t; 313 314 /* 315 * Local port state definitions 316 * NOTE that every time there is a state change, the newly set bit suggests 317 * the action. So far there are 3 actions S_PORT_CLEANUP, S_ADAPTER_FATAL 318 * and S_INIT_LINK. 319 */ 320 #define S_RCVD_LINK_DOWN 0x01 321 #define S_RCVD_LINK_UP 0x02 322 #define S_LINK_ONLINE 0x04 323 #define S_INIT_LINK 0x08 324 #define S_PORT_CLEANUP 0x10 325 326 #define PORT_STATE_LINK_DOWN 0x00 327 #define PORT_STATE_LINK_INIT_START (S_RCVD_LINK_UP | S_LINK_ONLINE |\ 328 S_INIT_LINK) 329 #define PORT_STATE_LINK_INIT_DONE (S_LINK_ONLINE) 330 #define PORT_STATE_LINK_UP_CLEANING (S_RCVD_LINK_UP | S_PORT_CLEANUP) 331 #define PORT_STATE_LINK_DOWN_CLEANING (S_RCVD_LINK_DOWN | S_PORT_CLEANUP) 332 333 /* 334 * Internal events 335 */ 336 #define FCT_I_EVENT_LINK_INIT_DONE 0x80 337 #define FCT_I_EVENT_CLEANUP_POLL 0x81 338 339 /* 340 * Offline processing states, used by worker thread. 341 */ 342 #define FCT_OPR_DONE 0 343 #define FCT_OPR_START 1 344 #define FCT_OPR_CMD_CLEANUP_WAIT 2 345 #define FCT_OPR_INT_CLEANUP_WAIT 3 346 347 /* 348 * Check time 349 */ 350 #define FCT_CMDLIST_CHECK_SECONDS 10 351 352 /* 353 * Define frequently used macros 354 */ 355 #define ICMD_TO_CT(x_icmd) \ 356 ((fct_sol_ct_t *)(x_icmd)->icmd_cmd->cmd_specific) 357 358 #define ICMD_TO_ELS(x_icmd) \ 359 ((fct_els_t *)(x_icmd)->icmd_cmd->cmd_specific) 360 361 #define ICMD_TO_IPORT(x_icmd) \ 362 ((fct_i_local_port_t *)(x_icmd)->icmd_cmd->cmd_port->port_fct_private) 363 364 #define ICMD_TO_PORT(x_icmd) \ 365 ((x_icmd)->icmd_cmd->cmd_port) 366 367 #define ICMD_TO_IRP(x_icmd) \ 368 ((fct_i_remote_port_t *)(x_icmd)->icmd_cmd->cmd_rp->rp_fct_private) 369 370 #define CMD_TO_ICMD(x_cmd) ((fct_i_cmd_t *)(x_cmd)->cmd_fct_private) 371 372 #define RP_TO_IRP(x_rp) ((fct_i_remote_port_t *)(x_rp)->rp_fct_private) 373 374 #define PORT_TO_IPORT(x_port) \ 375 ((fct_i_local_port_t *)(x_port)->port_fct_private) 376 377 #define FCT_IS_ELS_ACC(x_icmd) \ 378 (((x_icmd)->icmd_cmd->cmd_comp_status == FCT_SUCCESS) && \ 379 (ICMD_TO_ELS(x_icmd)->els_resp_payload[0] == ELS_OP_ACC)) 380 381 #define FCT_IS_CT_ACC(x_icmd) \ 382 (((x_icmd)->icmd_cmd->cmd_comp_status == FCT_SUCCESS) && \ 383 (ICMD_TO_CT(x_icmd)->ct_resp_payload[8] == 0x80) &&\ 384 (ICMD_TO_CT(x_icmd)->ct_resp_payload[9] == 0x02)) 385 386 #define IPORT_IN_NS_TOPO(x_iport) \ 387 ((x_iport)->iport_link_info.port_topology & PORT_TOPOLOGY_FABRIC_BIT) 388 389 #define IS_LOGO_ELS(icmd) \ 390 (ICMD_TO_ELS(icmd)->els_req_payload[0] == ELS_OP_LOGO) 391 392 stmf_status_t fct_xfer_scsi_data(scsi_task_t *task, 393 stmf_data_buf_t *dbuf, uint32_t ioflags); 394 stmf_status_t fct_send_scsi_status(scsi_task_t *task, uint32_t ioflags); 395 fct_i_remote_port_t *fct_portid_to_portptr(fct_i_local_port_t *iport, 396 uint32_t portid); 397 fct_i_remote_port_t *fct_lookup_irp_by_nodewwn(fct_i_local_port_t *iport, 398 uint8_t *nodewwn); 399 fct_i_remote_port_t *fct_lookup_irp_by_portwwn(fct_i_local_port_t *iport, 400 uint8_t *portwwn); 401 void fct_queue_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp); 402 void fct_deque_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp); 403 int fct_implicitly_logo_all(fct_i_local_port_t *iport, int force_implicit); 404 void fct_post_implicit_logo(fct_cmd_t *cmd); 405 void fct_rehash(fct_i_local_port_t *iport); 406 uint8_t fct_local_port_cleanup_done(fct_i_local_port_t *iport); 407 void fct_handle_rcvd_abts(fct_cmd_t *cmd); 408 void fct_fill_abts_acc(fct_cmd_t *cmd); 409 void fct_q_for_termination_lock_held(fct_i_local_port_t *iport, 410 fct_i_cmd_t *icmd, fct_status_t s); 411 disc_action_t fct_handle_port_offline(fct_i_local_port_t *iport); 412 disc_action_t fct_cmd_terminator(fct_i_local_port_t *iport); 413 void fct_cmd_free(fct_cmd_t *cmd); 414 void fct_scsi_task_free(scsi_task_t *task); 415 stmf_status_t fct_scsi_abort(stmf_local_port_t *lport, int abort_cmd, 416 void *arg, uint32_t flags); 417 stmf_status_t fct_info(uint32_t cmd, stmf_local_port_t *lport, 418 void *arg, uint8_t *buf, uint32_t *bufsizep); 419 void fct_event_handler(stmf_local_port_t *lport, int eventid, 420 void *arg, uint32_t flags); 421 uint16_t fct_alloc_cmd_slot(fct_i_local_port_t *iport, fct_cmd_t *cmd); 422 void fct_post_to_discovery_queue(fct_i_local_port_t *iport, 423 fct_i_remote_port_t *irp, fct_i_cmd_t *icmd); 424 fct_cmd_t *fct_create_solct(fct_local_port_t *port, fct_remote_port_t *rp, 425 uint16_t ctop, fct_icmd_cb_t icmdcb); 426 fct_cmd_t *fct_create_solels(fct_local_port_t *port, fct_remote_port_t *rp, 427 int implicit, uchar_t elsop, uint32_t wkdid, fct_icmd_cb_t icmdcb); 428 void fct_handle_solct(fct_cmd_t *cmd); 429 void fct_post_to_solcmd_queue(fct_local_port_t *port, fct_cmd_t *cmd); 430 void fct_logo_cb(fct_i_cmd_t *icmd); 431 void fct_link_init_cb(fct_i_cmd_t *icmd); 432 void fct_gsnn_cb(fct_i_cmd_t *icmd); 433 void fct_gcs_cb(fct_i_cmd_t *icmd); 434 void fct_gft_cb(fct_i_cmd_t *icmd); 435 void fct_gspn_cb(fct_i_cmd_t *icmd); 436 void fct_rls_cb(fct_i_cmd_t *icmd); 437 disc_action_t fct_process_link_init(fct_i_local_port_t *iport); 438 439 #ifdef __cplusplus 440 } 441 #endif 442 443 #endif /* _FCT_IMPL_H */ 444