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 _FC_PORTIF_H 27 #define _FC_PORTIF_H 28 29 30 #include <sys/note.h> 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 37 /* 38 * To remove the port WWN from the orphan list; An orphan list 39 * scan typically happens during ONLINE processing (after a LIP 40 * in Public loop or link reset) or during RSCN validation. 41 */ 42 #define FC_ORPHAN_SCAN_LIMIT 15 43 44 /* 45 * Show a limited tolerance on the number of LOGOs that an 46 * N/NL_Port can send; Beyond that it'll be removed entirely 47 * from the port driver's data base. The tolerance counter 48 * is reset after each link reset. 49 */ 50 #define FC_LOGO_TOLERANCE_LIMIT 16 51 #define FC_LOGO_TOLERANCE_TIME_LIMIT 5000000 /* 5 seconds */ 52 53 /* 54 * ns_flags field definitions in struct 55 * fctl_ns_req_t 56 */ 57 #define FCTL_NS_FILL_NS_MAP 0x01 58 #define FCTL_NS_GET_DEV_COUNT 0x02 59 #define FCTL_NS_NO_DATA_BUF 0x04 60 #define FCTL_NS_BUF_IS_USERLAND 0x08 61 #define FCTL_NS_BUF_IS_FC_PORTMAP 0x10 62 #define FCTL_NS_CREATE_DEVICE 0x20 63 #define FCTL_NS_VALIDATE_PD 0x40 64 #define FCTL_NS_ASYNC_REQUEST 0x80 65 #define FCTL_GAN_START_ID 0xFFFFFF 66 67 68 69 /* 70 * Values for the fp_soft_state field in the fc_local_port_t struct. 71 * 72 * Notice below that in two cases, suspend and pm-suspend,there 73 * is no usage of _IN_, which means the bits will stay even after 74 * suspend/pm-suspend is complete they are cleared at the time of 75 * resume/pm-resume. 76 */ 77 78 /* 79 * FP_SOFT_IN_DETACH is set in fp_detach_handler(), which is called from 80 * fp_detach() for the DDI_DETACH flag. FP_SOFT_IN_DETACH is checked in 81 * numerous places. It is never explicitly cleared -- apparently the code 82 * relies on ddi_softstate_free(9F) to clear it. 83 */ 84 #define FP_SOFT_IN_DETACH 0x0002 85 86 /* 87 * FP_SOFT_SUSPEND is set in fp_suspend_handler() and cleared in 88 * fp_resume_handler. It is tested in a number of placed in fp and fctl, 89 * including fp_job_handler(). 90 */ 91 #define FP_SOFT_SUSPEND 0x0004 92 93 /* 94 * FP_SOFT_POWER_DOWN is set in fp_power_down() and cleared in fp_power_up(). 95 * It is tested in a number of different places in fp/fctl. 96 */ 97 #define FP_SOFT_POWER_DOWN 0x0008 98 #define FP_SOFT_IN_STATEC_CB 0x0010 99 #define FP_SOFT_IN_UNSOL_CB 0x0020 100 #define FP_SOFT_IN_LINK_RESET 0x0040 101 #define FP_SOFT_BAD_LINK 0x0080 102 #define FP_SOFT_IN_FCA_RESET 0x0100 103 #define FP_DETACH_INPROGRESS 0x0200 104 #define FP_DETACH_FAILED 0x0400 105 #define FP_SOFT_NO_PMCOMP 0x0800 106 107 /* 108 * Instruct the port driver to just accept logins from these addresses 109 */ 110 #define FC_MUST_ACCEPT_D_ID(x) (FC_WELL_KNOWN_ADDR(x) || (x) == 0) 111 112 #define FC_IS_REAL_DEVICE(x) (!FC_MUST_ACCEPT_D_ID(x)) 113 114 /* 115 * Bit definitions for fp_options field in fc_local_port_t 116 * structure for Feature and Hack additions to make 117 * the driver code a real hairball. 118 */ 119 #define FP_NS_SMART_COUNT 0x01 120 #define FP_SEND_RJT 0x02 121 #define FP_CORE_ON_OFFLINE_TIMEOUT 0x04 122 #define FP_RESET_CORE_ON_OFFLINE_TIMEOUT 0x08 123 #define FP_TARGET_MODE 0x10 124 125 126 /* 127 * Values for fp_pm_level in the fc_local_port_t struct. Tracks current PM 128 * level for the local port. 129 */ 130 #define FP_PM_PORT_DOWN 0 131 #define FP_PM_PORT_UP 1 132 133 134 /* 135 * FC port compoment for PM. Used with pm_raise_power() and friends. 136 */ 137 #define FP_PM_COMPONENT 0 138 139 140 #define FCTL_WWN_SIZE(wwn) \ 141 (sizeof ((wwn)->raw_wwn) / sizeof ((wwn)->raw_wwn[0])) 142 143 144 /* 145 * Structure for issuing a work request to the per-instance "job handler" 146 * thread. Primarily allocated/initialized by fctl_alloc_job() and freed by 147 * fctl_dealloc_job(). fctl keeps a kmem_cache of these structs anchored by the 148 * fctl_job_cache global variable. The cache is created at fctl's _init(9E) and 149 * destroyed at fctl's _fini(9E). See also fctl_cache_constructor() 150 * and fctl_cache_destructor(). 151 */ 152 typedef struct job_request { 153 /* 154 * ID code for the job or task to be performed. Set by fctl_alloc_job() 155 * and read by fp_job_handler(). 156 */ 157 int job_code; 158 159 /* 160 * Completion status of the request. Typically FC_SUCCESS or 161 * FC_FAILURE, but may make use of other error code values (such as 162 * FC_OFFLINE, FC_BADCMD, FC_NO_MAP, and friends). The complete set 163 * of values is not clearly specified. 164 */ 165 int job_result; 166 167 /* Execution control flags (defined below) */ 168 int job_flags; 169 170 /* 171 * This allows multiple concurrent operations using the same 172 * job_request_t struct, such as a PLOGI to a group of remote ports 173 * (see fp_plogi_group()). 174 * 175 * This is why this scheme needs the job_mutex to protect 176 * the job_counter variable, plus the additional job_port_sema for 177 * synchronizing thread(s). 178 */ 179 int job_counter; 180 181 182 opaque_t job_cb_arg; /* callback func arg */ 183 184 kmutex_t job_mutex; 185 ksema_t job_fctl_sema; 186 ksema_t job_port_sema; 187 188 189 void (*job_comp) (opaque_t, uchar_t result); 190 fc_packet_t **job_ulp_pkts; 191 uint32_t job_ulp_listlen; /* packet list length */ 192 void *job_private; /* caller's private */ 193 void *job_arg; /* caller's argument */ 194 195 /* 196 * Pointer for singly-liked list of outstanding job_request structs, 197 * maintained on a per-instance basis by the fp_port_head and 198 * fp_port_tail pointers in the fc_local_port_t struct. 199 */ 200 struct job_request *job_next; 201 } job_request_t; 202 203 204 #if !defined(__lint) 205 _NOTE(SCHEME_PROTECTS_DATA("unique per request", 206 job_request::job_code job_request::job_result job_request::job_flags 207 job_request::job_cb_arg job_request::job_comp 208 job_request::job_ulp_pkts job_request::job_ulp_listlen 209 job_request::job_private job_request::job_arg)) 210 _NOTE(MUTEX_PROTECTS_DATA(fc_local_port::fp_mutex, job_request::job_next)) 211 _NOTE(MUTEX_PROTECTS_DATA(job_request::job_mutex, job_request::job_counter)) 212 #endif /* __lint */ 213 214 215 /* 216 * Values for the job_code field in the job_request_t struct. 217 */ 218 #define JOB_ATTACH_ULP 1 /* ULP call to fc_ulp_add() */ 219 #define JOB_PORT_STARTUP 2 220 #define JOB_PORT_GETMAP 3 221 #define JOB_PORT_GETMAP_PLOGI_ALL 4 222 #define JOB_PLOGI_ONE 5 223 #define JOB_PLOGI_GROUP 6 224 #define JOB_LOGO_ONE 7 225 #define JOB_PORT_OFFLINE 8 226 #define JOB_PORT_ONLINE 9 227 228 /* Prepare the local port and the driver softstate for a DDI_DETACH. */ 229 #define JOB_PORT_SHUTDOWN 10 230 231 /* Handle an unsolicited request in the job thread */ 232 #define JOB_UNSOL_REQUEST 11 233 234 #define JOB_NS_CMD 12 235 #define JOB_LINK_RESET 13 236 #define JOB_ULP_NOTIFY 14 237 238 #define JOB_FCIO_LOGIN 15 239 #define JOB_FCIO_LOGOUT 16 240 241 /* 242 * This is used for requests that will not actually be dispatched to the job 243 * thread. 244 */ 245 #define JOB_DUMMY 127 246 247 248 /* 249 * Bitmask values for the job_flags field in the job_request_t struct. 250 * 251 * JOB_TYPE_FCTL_ASYNC is set in various places in fp and fctl. If set then 252 * fctl_jobdone() will call the completion function in the job_comp field and 253 * deallocate the job_request_t struct. If not set then fctl_jobdone() will 254 * sema_v() the job_fctl_sema to wake up any waiting thread. This bit is also 255 * checked in fc_ulp_login(): if *clear* then fc_ulp_login() will call 256 * fctl_jobwait() in order to block the calling thread in the job_fctl_sema, and 257 * then call fctl_dealloc_job() after fctl_jobwait() returns. 258 * 259 * JOB_TYPE_FP_ASYNC is set in various places in fp. If set then fp_jobdone() 260 * will call fctl_jobdone(); if clear then fp_jobdone() will sema_v() the 261 * job_port_sema in the job_request_t. fp_port_shutdown() also looks for 262 * JOB_TYPE_FP_ASYNC. Just to keep thing interesting, JOB_TYPE_FP_ASYNC is 263 * also set in fp_validate_area_domain() and cleared in fp_fcio_login() and 264 * fp_ns_get_devcount() 265 * 266 * The apparent purpose of all this is to allow nested job requests to 267 * occur in parallel. 268 * 269 * JOB_CANCEL_ULP_NOTIFICATION appears to be intended to the number of 270 * state change callbacks that are reported to ULPs when mutiple state 271 * changes are being processed in parallel. 272 */ 273 #define JOB_TYPE_FCTL_ASYNC 0x01 274 #define JOB_TYPE_FP_ASYNC 0x02 275 #define JOB_CANCEL_ULP_NOTIFICATION 0x10 276 277 278 279 typedef struct fc_port_clist { 280 opaque_t clist_port; /* port handle */ 281 uint32_t clist_state; /* port state */ 282 uint32_t clist_len; /* map len */ 283 uint32_t clist_size; /* alloc len */ 284 fc_portmap_t *clist_map; /* changelist */ 285 uint32_t clist_flags; /* port topology */ 286 uint32_t clist_wait; /* for synchronous requests */ 287 kmutex_t clist_mutex; /* clist lock */ 288 kcondvar_t clist_cv; /* clist cv */ 289 } fc_port_clist_t; 290 291 #if !defined(__lint) 292 _NOTE(SCHEME_PROTECTS_DATA("unique per state change", fc_port_clist)) 293 #endif /* __lint */ 294 295 /* 296 * The cmd_size and resp_size shouldn't include the CT HEADER. 297 * 298 * For commands like GAN, the ns_resp_size should indicate the 299 * total number of bytes allocated in the ns_resp_buf to get all 300 * the NS objects. 301 */ 302 typedef struct fctl_ns_req { 303 int ns_result; 304 uint32_t ns_gan_index; 305 uint32_t ns_gan_sid; 306 uint32_t ns_flags; 307 uint16_t ns_cmd_code; /* NS command code */ 308 caddr_t ns_cmd_buf; /* NS command buffer */ 309 uint16_t ns_cmd_size; /* NS command length */ 310 uint16_t ns_resp_size; /* NS response length */ 311 caddr_t ns_data_buf; /* User buffer */ 312 uint32_t ns_data_len; /* User buffer length */ 313 uint32_t ns_gan_max; 314 fc_ct_header_t ns_resp_hdr; 315 fc_remote_port_t *ns_pd; 316 } fctl_ns_req_t; 317 318 #if !defined(__lint) 319 _NOTE(SCHEME_PROTECTS_DATA("unique per state change", fctl_ns_req)) 320 #endif /* __lint */ 321 322 /* 323 * Orphan list of Port WWNs 324 */ 325 typedef struct fc_orphan { 326 int orp_nscan; /* Number of scans */ 327 clock_t orp_tstamp; /* When it disappeared */ 328 la_wwn_t orp_pwwn; /* Port WWN */ 329 struct fc_orphan *orp_next; /* Next orphan */ 330 } fc_orphan_t; 331 332 #if !defined(__lint) 333 _NOTE(SCHEME_PROTECTS_DATA("scans don't interleave", 334 fc_orphan::orp_nscan fc_orphan::orp_pwwn fc_orphan::orp_tstamp)) 335 _NOTE(MUTEX_PROTECTS_DATA(fc_local_port::fp_mutex, fc_orphan::orp_next)) 336 #endif /* __lint */ 337 338 339 fc_remote_node_t *fctl_create_remote_node(la_wwn_t *nwwn, int sleep); 340 void fctl_destroy_remote_node(fc_remote_node_t *rnp); 341 fc_remote_port_t *fctl_create_remote_port(fc_local_port_t *port, 342 la_wwn_t *node_wwn, la_wwn_t *port_wwn, uint32_t d_id, 343 uchar_t recepient, int sleep); 344 int fctl_destroy_remote_port(fc_local_port_t *port, fc_remote_port_t *pd); 345 fc_remote_port_t *fctl_alloc_remote_port(fc_local_port_t *port, 346 la_wwn_t *port_wwn, uint32_t d_id, uchar_t recepient, int sleep); 347 void fctl_dealloc_remote_port(fc_remote_port_t *pd); 348 void fctl_release_remote_port(fc_remote_port_t *pd); 349 void fctl_destroy_all_remote_ports(fc_local_port_t *port); 350 void fctl_link_remote_port_to_remote_node(fc_remote_node_t *rnp, 351 fc_remote_port_t *pd); 352 int fctl_unlink_remote_port_from_remote_node(fc_remote_node_t *rnp, 353 fc_remote_port_t *pd); 354 355 job_request_t *fctl_alloc_job(int job_code, int job_flags, 356 void (*comp) (opaque_t, uchar_t), opaque_t arg, int sleep); 357 void fctl_dealloc_job(job_request_t *job); 358 void fctl_enque_job(fc_local_port_t *port, job_request_t *job); 359 void fctl_priority_enque_job(fc_local_port_t *port, job_request_t *job); 360 job_request_t *fctl_deque_job(fc_local_port_t *port); 361 void fctl_jobwait(job_request_t *job); 362 void fctl_jobdone(job_request_t *job); 363 364 void fctl_attach_ulps(fc_local_port_t *port, fc_attach_cmd_t cmd, 365 struct modlinkage *linkage); 366 int fctl_detach_ulps(fc_local_port_t *port, fc_detach_cmd_t cmd, 367 struct modlinkage *linkage); 368 369 void fctl_add_port(fc_local_port_t *port); 370 void fctl_remove_port(fc_local_port_t *port); 371 int fctl_busy_port(fc_local_port_t *port); 372 void fctl_idle_port(fc_local_port_t *port); 373 374 fc_remote_port_t *fctl_get_remote_port_by_did(fc_local_port_t *port, 375 uint32_t d_id); 376 fc_remote_port_t *fctl_hold_remote_port_by_did(fc_local_port_t *port, 377 uint32_t d_id); 378 fc_remote_port_t *fctl_get_remote_port_by_pwwn(fc_local_port_t *port, 379 la_wwn_t *pwwn); 380 fc_remote_port_t *fctl_hold_remote_port_by_pwwn(fc_local_port_t *port, 381 la_wwn_t *pwwn); 382 fc_remote_port_t * 383 fctl_get_remote_port_by_pwwn_mutex_held(fc_local_port_t *port, 384 la_wwn_t *pwwn); 385 fc_remote_node_t *fctl_get_remote_node_by_nwwn(la_wwn_t *node_wwn); 386 fc_remote_node_t *fctl_lock_remote_node_by_nwwn(la_wwn_t *node_wwn); 387 fc_remote_port_t *fctl_lookup_pd_by_did(fc_local_port_t *port, uint32_t d_id); 388 fc_remote_port_t *fctl_lookup_pd_by_index(fc_local_port_t *port, 389 uint32_t index); 390 fc_remote_port_t *fctl_lookup_pd_by_wwn(fc_local_port_t *port, la_wwn_t wwn); 391 392 void fctl_enlist_did_table(fc_local_port_t *port, fc_remote_port_t *pd); 393 void fctl_delist_did_table(fc_local_port_t *port, fc_remote_port_t *pd); 394 void fctl_enlist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd); 395 void fctl_delist_pwwn_table(fc_local_port_t *port, fc_remote_port_t *pd); 396 int fctl_enlist_nwwn_table(fc_remote_node_t *rnp, int sleep); 397 void fctl_delist_nwwn_table(fc_remote_node_t *rnp); 398 399 void fctl_ulp_statec_cb(void *arg); 400 void fctl_ulp_unsol_cb(fc_local_port_t *port, fc_unsol_buf_t *buf, 401 uchar_t type); 402 int fctl_ulp_port_ioctl(fc_local_port_t *port, dev_t dev, int cmd, 403 intptr_t data, int mode, cred_t *credp, int *rval); 404 405 void fctl_fillout_map(fc_local_port_t *port, fc_portmap_t **map, 406 uint32_t *len, int whole_map, int justcopy, int orphan); 407 void fctl_copy_portmap_held(fc_portmap_t *map, fc_remote_port_t *pd); 408 void fctl_copy_portmap(fc_portmap_t *map, fc_remote_port_t *pd); 409 410 fctl_ns_req_t *fctl_alloc_ns_cmd(uint32_t cmd_len, uint32_t resp_len, 411 uint32_t data_len, uint32_t ns_flags, int sleep); 412 void fctl_free_ns_cmd(fctl_ns_req_t *ns_cmd); 413 414 int fctl_remove_if_orphan(fc_local_port_t *port, la_wwn_t *pwwn); 415 int fctl_add_orphan_held(fc_local_port_t *port, fc_remote_port_t *pd); 416 int fctl_add_orphan(fc_local_port_t *port, fc_remote_port_t *pd, int sleep); 417 void fctl_remove_oldies(fc_local_port_t *port); 418 419 int fctl_is_wwn_zero(la_wwn_t *wwn); 420 int fctl_wwn_cmp(la_wwn_t *src, la_wwn_t *dst); 421 int fctl_atoi(caddr_t string, int base); 422 int fctl_count_fru_ports(fc_local_port_t *port, int npivflag); 423 fc_local_port_t *fctl_get_adapter_port_by_index(fc_local_port_t *port, 424 uint32_t port_index); 425 426 void fctl_tc_constructor(timed_counter_t *tc, uint32_t max_value, 427 clock_t timer); 428 void fctl_tc_destructor(timed_counter_t *tc); 429 boolean_t fctl_tc_increment(timed_counter_t *tc); 430 void fctl_tc_reset(timed_counter_t *tc); 431 432 #ifdef __cplusplus 433 } 434 #endif 435 436 #endif /* _FC_PORTIF_H */ 437