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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #define RSCN_OPTION_VERIFY 0x0001
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 */
39 LI_STATE_DO_FCLOGIN
, /* Login into 0xFFFFFD */
40 LI_STATE_DO_SCR
, /* State change registration */
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 */
49 LI_STATE_MAX
/* Not a real state */
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
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)
68 typedef void (* fct_icmd_cb_t
)(struct fct_i_cmd
*icmd
);
69 typedef struct fct_i_cmd
{
71 uint32_t icmd_alloc_size
;
72 fct_struct_id_t icmd_struct_id
;
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
;
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
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
104 #define ICMD_IN_SOLCMD_QUEUE 0x010000
105 #define ICMD_SOLCMD_NEW 0x020000
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
;
113 /* For queueing to local port */
114 struct fct_i_remote_port
*irp_next
;
116 /* For queueing to handle elses */
117 struct fct_i_remote_port
*irp_discovery_next
;
119 fct_i_cmd_t
*irp_els_list
;
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.
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
;
133 clock_t irp_deregister_timer
;
134 uint32_t irp_dereg_count
;
138 uint32_t irp_rcvd_prli_params
;
139 uint32_t irp_sent_prli_params
;
142 * Most HBAs will only register symbolic node name instead of port name,
143 * so we use SNN as session alias.
145 stmf_scsi_session_t
*irp_session
;
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 */
153 uint32_t irp_rscn_counter
;
154 } fct_i_remote_port_t
;
157 * structure used for fct_rls_cb() callback private data
159 typedef struct fct_rls_cb_data
{
160 struct fct_port_link_status
*fct_link_status
;
161 fct_status_t fct_els_res
;
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
177 typedef struct fct_cmd_slot
{
178 fct_i_cmd_t
*slot_cmd
;
181 uint8_t slot_uniq_cntr
;
183 #define FCT_SLOT_EOL 0xffff
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))
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
;
197 struct fct_i_local_port
*iport_next
;
198 struct fct_i_local_port
*iport_prev
;
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
;
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
;
218 * These variables are used to manage fct_cmd_t cache for SCSI traffic
221 * Total # of cmds allocated by the driver. Some of which are free
222 * and sitting on iport_cached_cmdlist. And some are executing.
224 uint32_t iport_total_alloced_ncmds
;
227 * Max active cmds in last interval (10 or 30 seconds)
229 uint32_t iport_max_active_ncmds
;
232 * # of free cmds sitting on the iport_cached_cmdlist
234 uint32_t iport_cached_ncmds
;
235 struct fct_i_cmd
*iport_cached_cmdlist
;
236 kmutex_t iport_cached_cmd_lock
;
239 * To release free cmds periodically
241 clock_t iport_cmdcheck_clock
;
243 uint16_t iport_task_green_limit
;
244 uint16_t iport_task_yellow_limit
;
245 uint16_t iport_task_red_limit
;
247 uint16_t iport_nslots_free
;
249 /* upper 16 bits is just a counter to avoid ABA issues */
250 uint32_t iport_next_free_slot
;
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
;
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
;
267 /* link initialization */
268 fct_status_t iport_li_comp_status
;
269 enum fct_li_state iport_li_state
;
271 /* solicited cmd link */
272 struct fct_i_cmd
*iport_solcmd_queue
;
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
;
282 #define IPORT_FLOGI_DONE(iport) PORT_FLOGI_DONE(&(iport)->iport_link_info)
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
294 #define IS_WORKER_SLEEPING(iport) ((iport)->iport_flags & \
295 (IPORT_WORKER_DOING_TIMEDWAIT | IPORT_WORKER_DOING_WAIT))
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
302 typedef struct fct_i_event
{
303 struct fct_i_event
*event_next
;
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
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
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
326 #define PORT_STATE_LINK_DOWN 0x00
327 #define PORT_STATE_LINK_INIT_START (S_RCVD_LINK_UP | S_LINK_ONLINE |\
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)
336 #define FCT_I_EVENT_LINK_INIT_DONE 0x80
337 #define FCT_I_EVENT_CLEANUP_POLL 0x81
340 * Offline processing states, used by worker thread.
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
350 #define FCT_CMDLIST_CHECK_SECONDS 10
353 * Define frequently used macros
355 #define ICMD_TO_CT(x_icmd) \
356 ((fct_sol_ct_t *)(x_icmd)->icmd_cmd->cmd_specific)
358 #define ICMD_TO_ELS(x_icmd) \
359 ((fct_els_t *)(x_icmd)->icmd_cmd->cmd_specific)
361 #define ICMD_TO_IPORT(x_icmd) \
362 ((fct_i_local_port_t *)(x_icmd)->icmd_cmd->cmd_port->port_fct_private)
364 #define ICMD_TO_PORT(x_icmd) \
365 ((x_icmd)->icmd_cmd->cmd_port)
367 #define ICMD_TO_IRP(x_icmd) \
368 ((fct_i_remote_port_t *)(x_icmd)->icmd_cmd->cmd_rp->rp_fct_private)
370 #define CMD_TO_ICMD(x_cmd) ((fct_i_cmd_t *)(x_cmd)->cmd_fct_private)
372 #define RP_TO_IRP(x_rp) ((fct_i_remote_port_t *)(x_rp)->rp_fct_private)
374 #define PORT_TO_IPORT(x_port) \
375 ((fct_i_local_port_t *)(x_port)->port_fct_private)
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))
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))
386 #define IPORT_IN_NS_TOPO(x_iport) \
387 ((x_iport)->iport_link_info.port_topology & PORT_TOPOLOGY_FABRIC_BIT)
389 #define IS_LOGO_ELS(icmd) \
390 (ICMD_TO_ELS(icmd)->els_req_payload[0] == ELS_OP_LOGO)
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
,
397 fct_i_remote_port_t
*fct_lookup_irp_by_nodewwn(fct_i_local_port_t
*iport
,
399 fct_i_remote_port_t
*fct_lookup_irp_by_portwwn(fct_i_local_port_t
*iport
,
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
);
443 #endif /* _FCT_IMPL_H */