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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #ifndef _STMF_IMPL_H 26 #define _STMF_IMPL_H 27 28 #include <sys/stmf_defines.h> 29 #include <sys/stmf_ioctl.h> 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 typedef uint32_t stmf_event_handle_t; 36 #define STMF_MAX_NUM_EVENTS (sizeof (stmf_event_handle_t) * 8) 37 #define STMF_EVENT_ADD(h, e) (atomic_or_32(&(h), \ 38 ((uint32_t)1) << (e))) 39 #define STMF_EVENT_REMOVE(h, e) (atomic_and_32(&(h), \ 40 ~(((uint32_t)1) << (e)))) 41 #define STMF_EVENT_ENABLED(h, e) (((h) & ((uint32_t)1) << (e)) != 0) 42 #define STMF_EVENT_CLEAR_ALL(h) ((h) = 0) 43 #define STMF_EVENT_ALLOC_HANDLE(h) ((h) = 0) 44 #define STMF_EVENT_FREE_HANDLE(h) ((h) = 0) 45 46 struct stmf_i_scsi_task; 47 struct stmf_itl_data; 48 49 typedef struct stmf_i_lu_provider { 50 stmf_lu_provider_t *ilp_lp; 51 uint32_t ilp_alloc_size; 52 uint32_t ilp_nlus; /* # LUNs being exported */ 53 uint32_t ilp_cb_in_progress:1, 54 ilp_rsvd:31; 55 struct stmf_i_lu_provider *ilp_next; 56 struct stmf_pp_data *ilp_ppd; 57 } stmf_i_lu_provider_t; 58 59 typedef struct stmf_i_lu { 60 stmf_lu_t *ilu_lu; 61 uint32_t ilu_alloc_size; 62 uint32_t ilu_flags; 63 uint32_t ilu_ref_cnt; 64 uint8_t ilu_state; 65 uint8_t ilu_prev_state; 66 stmf_event_handle_t ilu_event_hdl; 67 struct stmf_i_lu *ilu_next; 68 struct stmf_i_lu *ilu_prev; 69 char *ilu_alias; 70 kmutex_t ilu_task_lock; 71 uint32_t ilu_task_cntr1; 72 uint32_t ilu_task_cntr2; 73 uint32_t *ilu_cur_task_cntr; 74 uint32_t ilu_ntasks; /* # of tasks in the ilu_task list */ 75 uint32_t ilu_ntasks_free; /* # of tasks that are free */ 76 uint32_t ilu_ntasks_min_free; /* # minimal free tasks */ 77 struct stmf_i_scsi_task *ilu_tasks; 78 struct stmf_i_scsi_task *ilu_free_tasks; 79 struct stmf_itl_data *ilu_itl_list; 80 81 /* point to the luid entry in stmf_state.stmf_luid_list */ 82 void *ilu_luid; 83 } stmf_i_lu_t; 84 85 /* 86 * ilu_flags 87 */ 88 #define ILU_STALL_DEREGISTER 0x0001 89 #define ILU_RESET_ACTIVE 0x0002 90 91 typedef struct stmf_i_port_provider { 92 stmf_port_provider_t *ipp_pp; 93 uint32_t ipp_alloc_size; 94 uint32_t ipp_npps; 95 uint32_t ipp_cb_in_progress:1, 96 ipp_rsvd:31; 97 struct stmf_i_port_provider *ipp_next; 98 struct stmf_pp_data *ipp_ppd; 99 } stmf_i_port_provider_t; 100 101 typedef struct stmf_i_local_port { 102 stmf_local_port_t *ilport_lport; 103 uint32_t ilport_alloc_size; 104 uint32_t ilport_nsessions; 105 struct stmf_i_scsi_session *ilport_ss_list; 106 krwlock_t ilport_lock; 107 struct stmf_i_local_port *ilport_next; 108 struct stmf_i_local_port *ilport_prev; 109 uint8_t ilport_state; 110 uint8_t ilport_prev_state; 111 uint16_t ilport_rtpid; /* relative tpid */ 112 stmf_event_handle_t ilport_event_hdl; 113 clock_t ilport_last_online_clock; 114 clock_t ilport_avg_interval; 115 uint32_t ilport_online_times; 116 uint32_t ilport_flags; 117 /* which target group this port belongs to in stmf_state.stmf_tg_list */ 118 void *ilport_tg; 119 /* XXX Need something to track all the remote ports also */ 120 } stmf_i_local_port_t; 121 122 #define STMF_AVG_ONLINE_INTERVAL (30 * drv_usectohz(1000000)) 123 124 /* 125 * ilport flags 126 */ 127 #define ILPORT_FORCED_OFFLINE 0x01 128 #define ILPORT_SS_GOT_INITIAL_LUNS 0x02 129 130 typedef struct stmf_i_scsi_session { 131 stmf_scsi_session_t *iss_ss; 132 uint32_t iss_alloc_size; 133 uint32_t iss_flags; 134 struct stmf_i_scsi_session *iss_next; 135 /* 136 * Ideally we should maintain 2 maps. One would indicate a new map 137 * which will become available only upon receipt of a REPORT LUN 138 * cmd. 139 */ 140 struct stmf_lun_map *iss_sm; 141 /* 142 * which host group the host of this session belongs to in 143 * stmf_state.stmf_hg_list 144 */ 145 void *iss_hg; 146 krwlock_t *iss_lockp; 147 time_t iss_creation_time; 148 } stmf_i_scsi_session_t; 149 150 /* 151 * iss flags 152 */ 153 #define ISS_LUN_INVENTORY_CHANGED 0x0001 154 #define ISS_RESET_ACTIVE 0x0002 155 #define ISS_BEING_CREATED 0x0004 156 #define ISS_GOT_INITIAL_LUNS 0x0008 157 #define ISS_EVENT_ACTIVE 0x0010 158 159 #define ITASK_MAX_NCMDS 14 160 #define ITASK_DEFAULT_POLL_TIMEOUT 0 161 struct stmf_worker; 162 typedef struct stmf_i_scsi_task { 163 scsi_task_t *itask_task; 164 uint32_t itask_alloc_size; 165 uint32_t itask_flags; 166 struct stmf_worker *itask_worker; 167 uint32_t *itask_ilu_task_cntr; 168 struct stmf_i_scsi_task *itask_worker_next; 169 struct stmf_i_scsi_task *itask_lu_next; 170 struct stmf_i_scsi_task *itask_lu_prev; 171 struct stmf_i_scsi_task *itask_lu_free_next; 172 struct stmf_i_scsi_task *itask_abort_next; 173 struct stmf_itl_data *itask_itl_datap; 174 clock_t itask_start_time; /* abort and normal */ 175 /* For now we only support 4 parallel buffers. Should be enough. */ 176 stmf_data_buf_t *itask_dbufs[4]; 177 clock_t itask_poll_timeout; 178 uint8_t itask_cmd_stack[ITASK_MAX_NCMDS]; 179 uint8_t itask_ncmds; 180 uint8_t itask_allocated_buf_map; 181 uint16_t itask_cdb_buf_size; 182 } stmf_i_scsi_task_t; 183 184 #define ITASK_DEFAULT_ABORT_TIMEOUT 5 185 186 /* 187 * itask_flags 188 */ 189 #define ITASK_IN_FREE_LIST 0x0001 190 #define ITASK_IN_TRANSITION 0x0002 191 #define ITASK_IN_WORKER_QUEUE 0x0004 192 #define ITASK_BEING_ABORTED 0x0008 193 #define ITASK_BEING_COMPLETED 0x0010 194 #define ITASK_KNOWN_TO_TGT_PORT 0x0020 195 #define ITASK_KNOWN_TO_LU 0x0040 196 #define ITASK_LU_ABORT_CALLED 0x0080 197 #define ITASK_TGT_PORT_ABORT_CALLED 0x0100 198 #define ITASK_DEFAULT_HANDLING 0x0200 199 #define ITASK_CAUSING_LU_RESET 0x0400 200 #define ITASK_CAUSING_TARGET_RESET 0x0800 201 202 /* 203 * itask cmds. 204 */ 205 #define ITASK_CMD_MASK 0x1F 206 #define ITASK_CMD_BUF_NDX(cmd) (((uint8_t)(cmd)) >> 5) 207 #define ITASK_CMD_NEW_TASK 0x1 208 #define ITASK_CMD_DATA_XFER_DONE 0x2 209 #define ITASK_CMD_STATUS_DONE 0x3 210 #define ITASK_CMD_ABORT 0x4 211 #define ITASK_CMD_SEND_STATUS 0x5 212 #define ITASK_CMD_POLL 0x10 213 #define ITASK_CMD_POLL_LU (ITASK_CMD_POLL | 1) 214 #define ITASK_CMD_POLL_LPORT (ITASK_CMD_POLL | 2) 215 216 /* 217 * struct maintained on a per itl basis when the lu registers ITL handle. 218 */ 219 typedef struct stmf_itl_data { 220 uint32_t itl_counter; 221 uint8_t itl_flags; 222 uint8_t itl_hdlrm_reason; 223 uint16_t itl_lun; 224 void *itl_handle; 225 struct stmf_i_scsi_session *itl_session; 226 struct stmf_itl_data *itl_next; 227 } stmf_itl_data_t; 228 229 /* 230 * itl flags 231 */ 232 #define STMF_ITL_BEING_TERMINATED 0x01 233 234 /* 235 * data structures to maintain provider private data. 236 */ 237 typedef struct stmf_pp_data { 238 struct stmf_pp_data *ppd_next; 239 void *ppd_provider; 240 nvlist_t *ppd_nv; 241 uint32_t ppd_lu_provider:1, 242 ppd_port_provider:1, 243 ppd_rsvd:30; 244 uint32_t ppd_alloc_size; 245 char ppd_name[8]; 246 } stmf_pp_data_t; 247 248 typedef struct stmf_worker { 249 kthread_t *worker_tid; 250 stmf_i_scsi_task_t *worker_task_head; 251 stmf_i_scsi_task_t *worker_task_tail; 252 stmf_i_scsi_task_t *worker_wait_head; 253 stmf_i_scsi_task_t *worker_wait_tail; 254 kmutex_t worker_lock; 255 kcondvar_t worker_cv; 256 uint32_t worker_flags; 257 uint32_t worker_queue_depth; /* ntasks cur queued */ 258 uint32_t worker_max_qdepth_pu; /* maxqd / unit time */ 259 uint32_t worker_max_sys_qdepth_pu; /* for all workers */ 260 uint32_t worker_ref_count; /* # IOs referencing */ 261 } stmf_worker_t; 262 263 /* 264 * worker flags 265 */ 266 #define STMF_WORKER_STARTED 1 267 #define STMF_WORKER_ACTIVE 2 268 #define STMF_WORKER_TERMINATE 4 269 270 /* 271 * data struct for managing transfers. 272 */ 273 typedef struct stmf_xfer_data { 274 uint32_t alloc_size; /* Including this struct */ 275 uint32_t size_done; 276 uint32_t size_left; 277 uint8_t buf[4]; 278 } stmf_xfer_data_t; 279 280 /* 281 * Define frequently used macros 282 */ 283 #define TASK_TO_ITASK(x_task) \ 284 ((stmf_i_scsi_task_t *)(x_task)->task_stmf_private) 285 286 void stmf_dlun_init(); 287 stmf_status_t stmf_dlun_fini(); 288 void stmf_worker_init(); 289 stmf_status_t stmf_worker_fini(); 290 void stmf_task_free(scsi_task_t *task); 291 void stmf_task_lu_free(scsi_task_t *task); 292 void stmf_do_task_abort(scsi_task_t *task); 293 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, 294 uint8_t hdlrm_reason); 295 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, 296 void *arg, uint32_t flags); 297 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, 298 void *arg, uint32_t flags); 299 300 #ifdef __cplusplus 301 } 302 #endif 303 304 #endif /* _STMF_IMPL_H */ 305