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