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 26 #ifndef _FCSM_H 27 #define _FCSM_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #ifdef _KERNEL 34 35 /* 36 * Message printing flags 37 */ 38 #define SM_LOG 1 39 #define SM_CONSOLE 2 40 #define SM_LOG_AND_CONSOLE 3 41 42 /* 43 * Debug levels 44 */ 45 #define SMDL_TRACE 0x0001 46 #define SMDL_IO 0x0002 47 #define SMDL_ERR 0x0004 48 #define SMDL_INFO 0x0008 49 50 #ifdef DEBUG 51 #define FCSM_DEBUG(level, args) \ 52 if (fcsm_debug & (level)) fcsm_display args 53 54 extern uint32_t fcsm_debug; 55 #else /* DEBUG */ 56 #define FCSM_DEBUG(level, args) 57 #endif /* DEBUG */ 58 59 #define FCSM_INIT_INSTANCES 8 /* # of instances for soft_state_init */ 60 /* 61 * Open flags 62 */ 63 #define FCSM_IDLE 0x00 64 #define FCSM_OPEN 0x01 65 #define FCSM_EXCL 0x02 66 67 #define FCSM_ELS_TIMEOUT (20) /* secs */ 68 #define FCSM_MS_TIMEOUT (20) /* secs */ 69 70 #define FCSM_OFFLINE_TICKER (120) /* secs */ 71 72 /* Definitions for command retries */ 73 #define FCSM_MAX_CMD_RETRIES 5 /* Max retries in case of failure */ 74 #define FCSM_RETRY_INTERVAL 3 /* Retry interval in seconds */ 75 #define FCSM_RETRY_TICKER 1 /* Retry thread execution interval */ 76 77 #define FCSM_MAX_JOB_RETRIES 3 /* Max retries in case of job failure */ 78 79 /* 80 * fcsm_job - Job structure to issue commands using command thread 81 */ 82 typedef struct fcsm_job { 83 uint32_t job_code; /* Command code */ 84 uint32_t job_flags; /* Command Flags */ 85 int job_port_instance; /* port driver instance */ 86 int job_result; /* job completion result */ 87 opaque_t job_arg; /* Command Arguments */ 88 opaque_t job_caller_priv; /* Caller private */ 89 void (*job_comp)(opaque_t, struct fcsm_job *, int); 90 /* completion func */ 91 opaque_t job_comp_arg; /* Arg for completion func */ 92 kmutex_t job_mutex; /* per command mutex */ 93 ksema_t job_sema; /* To wait for completion */ 94 struct fcsm_job *job_next; /* for linked list */ 95 int job_retry_count; /* Retry count */ 96 void *job_priv; /* for fcsm private use */ 97 uint32_t job_priv_flags; /* fcsm private flags */ 98 } fcsm_job_t; 99 100 /* 101 * fcsm_t - FCSM Structure for per port information 102 */ 103 typedef struct fcsm { 104 kmutex_t sm_mutex; /* mutex for protection */ 105 struct fcsm *sm_next; /* for global linked list */ 106 int sm_sid; /* FCA Port ID */ 107 int sm_instance; /* fc port instance number */ 108 uint32_t sm_port_state; /* FCA port state */ 109 uint32_t sm_port_top; /* Port topology */ 110 uint32_t sm_state; /* San Mgmt State information */ 111 uint32_t sm_flags; /* San Mgmt Flags (see below) */ 112 int sm_ncmds; /* # of pending commands */ 113 int sm_cb_count; /* # callbacks in progress */ 114 fc_ulp_port_info_t sm_port_info; /* FCA Port Information */ 115 fcsm_job_t *sm_job_head; /* port's job queue head */ 116 fcsm_job_t *sm_job_tail; /* port's job queue tail */ 117 struct fcsm_cmd *sm_retry_head; /* cmd retry queue head */ 118 struct fcsm_cmd *sm_retry_tail; /* cmd retry queue tail */ 119 timeout_id_t sm_retry_tid; /* retry timer */ 120 timeout_id_t sm_offline_tid; /* offline timer */ 121 kcondvar_t sm_job_cv; /* cv for job processing */ 122 uint32_t sm_dev_count; /* # of devices discovered */ 123 fc_portmap_t *sm_portmap; /* device map */ 124 kthread_t *sm_thread; /* per port job thread */ 125 kmem_cache_t *sm_cmd_cache; /* per port fc packet cache */ 126 la_els_logi_t sm_ms_service_params; 127 /* Mgmt Server Login Params */ 128 callb_cpr_t sm_cpr_info; /* CPR info */ 129 } fcsm_t; 130 131 132 typedef struct fcsm_cmd { 133 fc_packet_t *cmd_fp_pkt; 134 fcsm_job_t *cmd_job; 135 fcsm_t *cmd_fcsm; 136 int cmd_retry_count; 137 int cmd_retry_interval; 138 int cmd_max_retries; 139 struct fcsm_cmd *cmd_next; 140 void (*cmd_comp)(struct fcsm_cmd *); 141 int (*cmd_transport)(opaque_t, fc_packet_t *); 142 uint32_t cmd_dma_flags; 143 fc_packet_t cmd_fc_packet; 144 } fcsm_cmd_t; 145 146 /* 147 * sm_flags in the per port FCSM Structure 148 */ 149 #define FCSM_ATTACHING 0x0001 150 #define FCSM_ATTACHED 0x0002 151 #define FCSM_DETACHING 0x0004 152 #define FCSM_DETACHED 0x0008 153 #define FCSM_SUSPENDED 0x0010 154 #define FCSM_POWER_DOWN 0x0020 155 #define FCSM_RESTORE_RETRY_TIMEOUT 0x0040 156 #define FCSM_RESTORE_OFFLINE_TIMEOUT 0x0080 157 #define FCSM_RETRY_TIMER_ACTIVE 0x0100 158 #define FCSM_SERIALIZE_JOBTHREAD 0x0200 159 #define FCSM_CMD_RETRY_Q_SUSPENDED 0x0400 160 #define FCSM_PORT_OFFLINE 0x0800 161 #define FCSM_LINK_DOWN 0x1000 162 #define FCSM_MGMT_SERVER_LOGGED_IN 0x2000 163 #define FCSM_MGMT_SERVER_LOGIN_IN_PROG 0x4000 164 #define FCSM_USING_NODMA_FCA 0x8000 165 166 /* Command flags for Job structure */ 167 #define FCSM_JOBFLAG_SYNC 0x01 168 #define FCSM_JOBFLAG_ASYNC 0x02 169 #define FCSM_JOBFLAG_SERIALIZE 0x04 170 #define FCSM_JOBFLAG_CTHEADER_BE 0X08 171 172 /* Command codes */ 173 #define FCSM_JOB_NONE 0x00 174 #define FCSM_JOB_THREAD_SHUTDOWN 0x01 175 #define FCSM_JOB_LOGIN_NAME_SERVER 0x02 176 #define FCSM_JOB_LOGIN_MGMT_SERVER 0x03 177 #define FCSM_JOB_CT_PASSTHRU 0x04 178 179 /* Private flags for command */ 180 #define FCSM_JOB_PRIV_WAIT_FOR_LOGIN 0x01 181 #define FCSM_JOB_PRIV_LOGIN_IN_PROG 0x02 182 183 /* Command DMA Flags */ 184 #define FCSM_CF_CMD_VALID_DMA_MEM 0x01 185 #define FCSM_CF_CMD_VALID_DMA_BIND 0x02 186 #define FCSM_CF_RESP_VALID_DMA_MEM 0x04 187 #define FCSM_CF_RESP_VALID_DMA_BIND 0x08 188 189 #define FCSM_INIT_CMD(cmd, job, tran_flags, tran_type, max_retries, func) { \ 190 (cmd)->cmd_job = (job); \ 191 (cmd)->cmd_fc_packet.pkt_tran_flags = (tran_flags); \ 192 (cmd)->cmd_fc_packet.pkt_tran_type = (tran_type); \ 193 (cmd)->cmd_max_retries = max_retries; \ 194 (cmd)->cmd_comp = func; \ 195 } 196 197 /* 198 * Macros to address endian issues 199 * local variable "fcsm" must exist before using these 200 */ 201 #define FCSM_REP_RD(handle, hostaddr, devaddr, cnt) \ 202 { \ 203 if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) { \ 204 ddi_rep_get8((handle), (uint8_t *)(hostaddr), \ 205 (uint8_t *)(devaddr), (cnt), \ 206 DDI_DEV_AUTOINCR); \ 207 } else { \ 208 bcopy((devaddr), (hostaddr), (cnt)); \ 209 } \ 210 } 211 212 #define FCSM_REP_WR(handle, hostaddr, devaddr, cnt) \ 213 { \ 214 if (!((fcsm)->sm_flags & FCSM_USING_NODMA_FCA)) { \ 215 ddi_rep_put8((handle), (uint8_t *)(hostaddr), \ 216 (uint8_t *)(devaddr), (cnt), \ 217 DDI_DEV_AUTOINCR); \ 218 } else { \ 219 bcopy((hostaddr), (devaddr), (cnt)); \ 220 } \ 221 } 222 223 #endif /* _KERNEL */ 224 225 /* 226 * IOCTL Definitions 227 */ 228 typedef struct fc_ct_aiu { 229 fc_ct_header_t aiu_header; 230 char aiu_payload[1]; 231 /* aiu_payload can be up to 'm' bytes (arbitrary length) */ 232 } fc_ct_aiu_t; 233 234 #define FCSMIO ('S' << 8) 235 #define FCSMIO_CMD (FCSMIO | 2000) 236 237 #define FCSMIO_SUB_CMD ('Y' << 8) 238 #define FCSMIO_CT_CMD (FCSMIO_SUB_CMD + 0x01) 239 #define FCSMIO_ADAPTER_LIST (FCSMIO_SUB_CMD + 0x02) 240 #define FCSMIO_FIND_ADAPTER (FCSMIO_SUB_CMD + 0x03) 241 242 #define FCSM_MAX_CT_SIZE (65536) /* 64K */ 243 244 /* Management Server - Fabric Configuration Server Commands */ 245 #define MS_CS_GTIN 0x0100 /* Get Topology Information */ 246 #define MS_CS_GIEL 0x0101 /* Get Interconnect Element List */ 247 #define MS_CS_GIET 0x0111 /* Get Interconnect Element Type */ 248 #define MS_CS_GDID 0x0112 /* Get Domain Identifier */ 249 #define MS_CS_GMID 0x0113 /* Get Management Identifier */ 250 #define MS_CS_GFN 0x0114 /* Get Fabric Name */ 251 #define MS_CS_GIELN 0x0115 /* Get Interconnect Element Logical Name */ 252 #define MS_CS_GMAL 0x0116 /* Get Management Address List */ 253 #define MS_CS_GIEIL 0x0117 /* Get Interconnect Element Information List */ 254 #define MS_CS_GPL 0x0118 /* Get Port List */ 255 #define MS_CS_GPT 0x0121 /* Get Port Type */ 256 #define MS_CS_GPPN 0x0122 /* Get Physical Port Number */ 257 #define MS_CS_GAPNL 0x0124 /* Get Attached Port Name List */ 258 #define MS_CS_GPS 0x0126 /* Get Port State */ 259 #define MS_CS_GATIN 0x0128 /* Get Attached Topology Information */ 260 #define MS_CS_GPLNL 0x0191 /* Get Platform Node Name List */ 261 #define MS_CS_GPLT 0x0192 /* Get Platform Type */ 262 #define MS_CS_GPLML 0x0193 /* Get Platform Management Address List */ 263 #define MS_CS_GNPL 0x01a1 /* Get Platform Name - Node Name */ 264 #define MS_CS_GPNL 0x01a2 /* Get Platform Name List */ 265 #define MS_CS_GNID 0x01b1 /* Get Node Identification Data - Node Name */ 266 #define MS_CS_RIELN 0x0215 /* Register Interconnect Element Logical Name */ 267 #define MS_CS_RPL 0x0280 /* Register Platform */ 268 #define MS_CS_RPLN 0x0291 /* Register Platform Name */ 269 #define MS_CS_RPLT 0x0292 /* Register Platform Type */ 270 #define MS_CS_RPLM 0x0293 /* Register Platform Management Address */ 271 #define MS_CS_DPL 0x0380 /* Deregister Platform */ 272 #define MS_CS_DPLN 0x0391 /* Deregister Platform Node Name */ 273 #define MS_CS_DPLML 0x0393 /* Deregister Platform Management Addr List */ 274 275 #ifdef _KERNEL 276 277 /* 278 * Driver entry point functions 279 */ 280 static int fcsm_attach(dev_info_t *, ddi_attach_cmd_t); 281 static int fcsm_detach(dev_info_t *, ddi_detach_cmd_t); 282 static int fcsm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 283 static int fcsm_open(dev_t *, int, int, cred_t *); 284 static int fcsm_close(dev_t, int, int, cred_t *); 285 static int fcsm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 286 287 /* 288 * FC Transport functions 289 */ 290 static int fcsm_port_attach(opaque_t, fc_ulp_port_info_t *, 291 fc_attach_cmd_t, uint32_t); 292 static int fcsm_port_detach(opaque_t, fc_ulp_port_info_t *, 293 fc_detach_cmd_t); 294 static int fcsm_port_ioctl(opaque_t, opaque_t, dev_t, int, intptr_t, 295 int, cred_t *, int *, uint32_t); 296 static void fcsm_statec_cb(opaque_t, opaque_t, uint32_t, uint32_t, 297 fc_portmap_t *, uint32_t, uint32_t); 298 static int fcsm_els_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t); 299 static int fcsm_data_cb(opaque_t, opaque_t, fc_unsol_buf_t *, uint32_t); 300 301 /* 302 * Internal functions 303 */ 304 static int fcsm_handle_port_attach(fc_ulp_port_info_t *, uint32_t, int); 305 static int fcsm_handle_port_resume(opaque_t, fc_ulp_port_info_t *, 306 fc_attach_cmd_t, uint32_t, fcsm_t *); 307 static int fcsm_handle_port_detach(fc_ulp_port_info_t *, fcsm_t *, 308 fc_detach_cmd_t); 309 static void fcsm_suspend_port(fcsm_t *); 310 static void fcsm_resume_port(fcsm_t *); 311 static void fcsm_cleanup_port(fcsm_t *); 312 static void fcsm_offline_timeout(void *); 313 static int fcsm_fciocmd(intptr_t, int, cred_t *, fcio_t *); 314 static int fcsm_fcio_copyout(fcio_t *, intptr_t, int); 315 static int fcsm_job_cache_constructor(void *, void *, int); 316 static void fcsm_job_cache_destructor(void *, void *); 317 static fcsm_job_t *fcsm_alloc_job(int); 318 static void fcsm_dealloc_job(fcsm_job_t *); 319 static void fcsm_init_job(fcsm_job_t *, int, uint32_t, uint32_t, opaque_t, 320 opaque_t, void (*comp)(opaque_t, fcsm_job_t *, int), 321 opaque_t); 322 static int fcsm_process_job(fcsm_job_t *, int); 323 static void fcsm_enque_job(fcsm_t *, fcsm_job_t *, int); 324 static fcsm_job_t *fcsm_deque_job(fcsm_t *); 325 static int fcsm_cmd_cache_constructor(void *, void *, int); 326 static void fcsm_cmd_cache_destructor(void *, void *); 327 static fcsm_cmd_t *fcsm_alloc_cmd(fcsm_t *, uint32_t, uint32_t, int); 328 static void fcsm_free_cmd_dma(fcsm_cmd_t *); 329 static void fcsm_job_thread(fcsm_t *); 330 static int fcsm_retry_job(fcsm_t *fcsm, fcsm_job_t *job); 331 static void fcsm_jobdone(fcsm_job_t *); 332 static void fcsm_ct_init(fcsm_t *, fcsm_cmd_t *, fc_ct_aiu_t *, size_t, 333 void (*comp_func)()); 334 static void fcsm_ct_intr(fcsm_cmd_t *); 335 static void fcsm_job_ct_passthru(fcsm_job_t *); 336 static int fcsm_login_and_process_job(fcsm_t *, fcsm_job_t *); 337 static void fcsm_login_ms_comp(opaque_t, fcsm_job_t *, int); 338 static void fcsm_els_init(fcsm_cmd_t *, uint32_t); 339 static int fcsm_xlogi_init(fcsm_t *, fcsm_cmd_t *, uint32_t, 340 void (*comp_func)(), uchar_t); 341 static void fcsm_xlogi_intr(fcsm_cmd_t *); 342 static void fcsm_job_login_mgmt_server(fcsm_job_t *); 343 int fcsm_ct_passthru(int, fcio_t *, int, int, 344 void (*func)(fcio_t *)); 345 static void fcsm_ct_passthru_comp(opaque_t, fcsm_job_t *, int); 346 static void fcsm_pkt_common_intr(fc_packet_t *); 347 static int fcsm_issue_cmd(fcsm_cmd_t *); 348 static int fcsm_retry_cmd(fcsm_cmd_t *); 349 static void fcsm_enque_cmd(fcsm_t *, fcsm_cmd_t *); 350 static fcsm_cmd_t *fcsm_deque_cmd(fcsm_t *); 351 static void fcsm_retry_timeout(void *); 352 static void fcsm_force_port_detach_all(void); 353 354 355 /* 356 * Utility functions 357 */ 358 static void fcsm_disp_devlist(fcsm_t *, fc_portmap_t *, uint32_t); 359 360 static void fcsm_display(int, int, fcsm_t *, 361 fc_packet_t *, const char *, ...); 362 int fcsm_pkt_state_to_rval(uchar_t, uint32_t); 363 caddr_t fcsm_port_state_to_str(uint32_t); 364 caddr_t fcsm_topology_to_str(uint32_t); 365 static caddr_t fcsm_dev_type_to_str(uint32_t); 366 367 368 #endif /* _KERNEL */ 369 370 371 #ifdef __cplusplus 372 } 373 #endif 374 375 #endif /* _FCSM_H */ 376