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 /* 23 * Copyright 2010 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <emlxs.h> 29 30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31 EMLXS_MSG_DEF(EMLXS_FCF_C); 32 33 /* 34 * STATE MACHINE RULES: 35 * 36 * - State change requests to an XXXX object when operating within 37 * an emlxs_XXXX state management function must be made 38 * using the emlxs_XXXX_state() call. 39 * 40 * - State change requests to an XXXX object when operating outside 41 * an emlxs_XXXX state management function must be made 42 * using the emlxs_XXXX_alloc(), emlxs_XXXX_free(), emlxs_XXXX_event() 43 * or emlxs_XXXX_..._notify() calls. 44 * 45 * - emlxs_XXXX_..._notify() calls are used by routines outside 46 * this fcf module to enter the state machine. 47 * 48 * - It is forbidden to make direct calls to emlxs_XXXX_...._action() 49 * functions. Only emlxs_XXXX_action() routines may make calls to 50 * emlxs_XXXX_...._action() functions. 51 * 52 * - Its is forbidden to make direct calls to emlxs_XXXX_action(). 53 * Only emlxs_XXXX_state() and emlxs_XXXX_event() routines may make 54 * calls to emlxs_XXXX_action(). 55 * 56 * - The EMLXS_FCF_LOCK must be held before calling: 57 * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action(). 58 * 59 * - All other calls touching fctab, fcfi, vfi, vpi, rpi objects must hold 60 * the EMLXS_FCF_LOCK to protect these objects. 61 */ 62 63 /* ************************************************************************** */ 64 /* FCF Generic */ 65 /* ************************************************************************** */ 66 67 /* 68 * EVENT ARG1 69 * -------------------------------------------- 70 * FCF_EVENT_STATE_ENTER None 71 * 72 * FCF_EVENT_LINKUP None 73 * FCF_EVENT_LINKDOWN None 74 * FCF_EVENT_CVL vpi 75 * FCF_EVENT_FCFTAB_FULL None 76 * FCF_EVENT_FCF_FOUND fcf_index 77 * FCF_EVENT_FCF_LOST fcf_index 78 * FCF_EVENT_FCF_CHANGED fcf_index 79 * 80 * FCF_EVENT_FCFI_ONLINE FCFIobj_t* 81 * FCF_EVENT_FCFI_OFFLINE FCFIobj_t* 82 * FCF_EVENT_FCFI_PAUSE FCFIobj_t* 83 * 84 * FCF_EVENT_VFI_ONLINE VFIobj_t* 85 * FCF_EVENT_VFI_OFFLINE VFIobj_t* 86 * FCF_EVENT_VFI_PAUSE VFIobj_t* 87 * 88 * FCF_EVENT_VPI_ONLINE VPIobj_t* 89 * FCF_EVENT_VPI_OFFLINE VPIobj_t* 90 * FCF_EVENT_VPI_PAUSE VPIobj_t* 91 * 92 * FCF_EVENT_RPI_ONLINE RPIobj_t* 93 * FCF_EVENT_RPI_OFFLINE RPIobj_t* 94 * FCF_EVENT_RPI_PAUSE RPIobj_t* 95 * FCF_EVENT_RPI_RESUME RPIobj_t* 96 */ 97 98 /* Order does not matter */ 99 emlxs_table_t emlxs_fcf_event_table[] = 100 { 101 {FCF_EVENT_STATE_ENTER, "STATE_ENTER"}, 102 103 {FCF_EVENT_SHUTDOWN, "SHUTDOWN"}, 104 {FCF_EVENT_LINKUP, "LINK_UP"}, 105 {FCF_EVENT_LINKDOWN, "LINK_DOWN"}, 106 {FCF_EVENT_CVL, "CVL_RECD"}, 107 {FCF_EVENT_FCFTAB_FULL, "TABLE_FULL"}, 108 {FCF_EVENT_FCF_FOUND, "FCF_FOUND"}, 109 {FCF_EVENT_FCF_LOST, "FCF_LOST"}, 110 {FCF_EVENT_FCF_CHANGED, "FCF_CHANGED"}, 111 112 {FCF_EVENT_FCFI_ONLINE, "FCFI_ONLINE"}, 113 {FCF_EVENT_FCFI_OFFLINE, "FCFI_OFFLINE"}, 114 {FCF_EVENT_FCFI_PAUSE, "FCFI_PAUSE"}, 115 116 {FCF_EVENT_VFI_ONLINE, "VFI_ONLINE"}, 117 {FCF_EVENT_VFI_OFFLINE, "VFI_OFFLINE"}, 118 {FCF_EVENT_VFI_PAUSE, "VFI_PAUSE"}, 119 120 {FCF_EVENT_VPI_ONLINE, "VPI_ONLINE"}, 121 {FCF_EVENT_VPI_OFFLINE, "VPI_OFFLINE"}, 122 {FCF_EVENT_VPI_PAUSE, "VPI_PAUSE"}, 123 124 {FCF_EVENT_RPI_ONLINE, "RPI_ONLINE"}, 125 {FCF_EVENT_RPI_OFFLINE, "RPI_OFFLINE"}, 126 {FCF_EVENT_RPI_PAUSE, "RPI_PAUSE"}, 127 {FCF_EVENT_RPI_RESUME, "RPI_RESUME"}, 128 129 }; /* emlxs_fcf_event_table */ 130 131 132 /* Order does not matter */ 133 emlxs_table_t emlxs_fcf_reason_table[] = 134 { 135 {FCF_REASON_NONE, "REASON_NONE"}, 136 {FCF_REASON_REENTER, "REASON_REENTER"}, 137 {FCF_REASON_EVENT, "REASON_EVENT"}, 138 {FCF_REASON_REQUESTED, "REASON_REQUESTED"}, 139 {FCF_REASON_NO_MBOX, "REASON_NO_MBOX"}, 140 {FCF_REASON_NO_BUFFER, "REASON_NO_BUFFER"}, 141 {FCF_REASON_SEND_FAILED, "REASON_SEND_FAILED"}, 142 {FCF_REASON_MBOX_FAILED, "REASON_MBOX_FAILED"}, 143 {FCF_REASON_NO_FCFI, "REASON_NO_FCFI"}, 144 {FCF_REASON_NO_VFI, "REASON_NO_VFI"}, 145 {FCF_REASON_ONLINE_FAILED, "REASON_ONLINE_FAILED"}, 146 {FCF_REASON_OFFLINE_FAILED, "REASON_OFFLINE_FAILED"}, 147 {FCF_REASON_OP_FAILED, "REASON_OP_FAILED"}, 148 {FCF_REASON_NO_PKT, "FCF_REASON_NO_PKT"}, 149 {FCF_REASON_NO_NODE, "FCF_REASON_NO_NODE"}, 150 {FCF_REASON_NOT_ALLOWED, "FCF_REASON_NOT_ALLOWED"}, 151 152 }; /* emlxs_fcf_reason_table */ 153 154 155 /* ********************************************************************** */ 156 /* FCFTAB */ 157 /* ********************************************************************** */ 158 159 /* Order does not matter */ 160 emlxs_table_t emlxs_fcftab_state_table[] = 161 { 162 {FCFTAB_STATE_SHUTDOWN, "FCFTAB_STATE_SHUTDOWN"}, 163 {FCFTAB_STATE_OFFLINE, "FCFTAB_STATE_OFFLINE"}, 164 165 {FCFTAB_STATE_SOLICIT, "FCFTAB_STATE_SOLICIT"}, 166 {FCFTAB_STATE_SOLICIT_FAILED, "FCFTAB_STATE_SOLICIT_FAILED"}, 167 {FCFTAB_STATE_SOLICIT_CMPL, "FCFTAB_STATE_SOLICIT_CMPL"}, 168 169 {FCFTAB_STATE_READ, "FCFTAB_STATE_READ"}, 170 {FCFTAB_STATE_READ_FAILED, "FCFTAB_STATE_READ_FAILED"}, 171 {FCFTAB_STATE_READ_CMPL, "FCFTAB_STATE_READ_CMPL"}, 172 173 {FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_STATE_FCFI_OFFLINE"}, 174 {FCFTAB_STATE_FCFI_OFFLINE_CMPL, "FCFTAB_STATE_FCFI_OFFLINE_CMPL"}, 175 176 {FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_STATE_FCFI_ONLINE"}, 177 {FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_STATE_FCFI_ONLINE_CMPL"}, 178 179 {FCFTAB_STATE_ONLINE, "FCFTAB_STATE_ONLINE"}, 180 181 }; /* emlxs_fcftab_state_table */ 182 183 184 static uint32_t emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port, 185 uint32_t evt, void *arg1); 186 static uint32_t emlxs_fcftab_sol_failed_action(emlxs_port_t *port, 187 uint32_t evt, void *arg1); 188 static uint32_t emlxs_fcftab_sol_action(emlxs_port_t *port, 189 uint32_t evt, void *arg1); 190 static uint32_t emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port, 191 uint32_t evt, void *arg1); 192 static uint32_t emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port, 193 uint32_t evt, void *arg1); 194 static uint32_t emlxs_fcftab_read_action(emlxs_port_t *port, 195 uint32_t evt, void *arg1); 196 static uint32_t emlxs_fcftab_read_failed_action(emlxs_port_t *port, 197 uint32_t evt, void *arg1); 198 static uint32_t emlxs_fcftab_read_cmpl_action(emlxs_port_t *port, 199 uint32_t evt, void *arg1); 200 static uint32_t emlxs_fcftab_fcfi_online_action(emlxs_port_t *port, 201 uint32_t evt, void *arg1); 202 static uint32_t emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, 203 uint32_t evt, void *arg1); 204 static uint32_t emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port, 205 uint32_t evt, void *arg1); 206 static uint32_t emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, 207 uint32_t evt, void *arg1); 208 static uint32_t emlxs_fcftab_found_evt_action(emlxs_port_t *port, 209 uint32_t evt, void *arg1); 210 static uint32_t emlxs_fcftab_lost_evt_action(emlxs_port_t *port, 211 uint32_t evt, void *arg1); 212 static uint32_t emlxs_fcftab_changed_evt_action(emlxs_port_t *port, 213 uint32_t evt, void *arg1); 214 static uint32_t emlxs_fcftab_full_evt_action(emlxs_port_t *port, 215 uint32_t evt, void *arg1); 216 static uint32_t emlxs_fcftab_linkup_evt_action(emlxs_port_t *port, 217 uint32_t evt, void *arg1); 218 static uint32_t emlxs_fcftab_cvl_evt_action(emlxs_port_t *port, 219 uint32_t evt, void *arg1); 220 static uint32_t emlxs_fcftab_online_action(emlxs_port_t *port, 221 uint32_t evt, void *arg1); 222 static uint32_t emlxs_fcftab_offline_action(emlxs_port_t *port, 223 uint32_t evt, void *arg1); 224 static uint32_t emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, 225 uint32_t evt, void *arg1); 226 static uint32_t emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port, 227 uint32_t evt, void *arg1); 228 static uint32_t emlxs_fcftab_shutdown_action(emlxs_port_t *port, 229 uint32_t evt, void *arg1); 230 231 static void emlxs_fcftab_read_timer(emlxs_hba_t *hba); 232 static void emlxs_fcftab_sol_timer(emlxs_hba_t *hba); 233 static void emlxs_fcftab_offline_timer(emlxs_hba_t *hba); 234 static char *emlxs_fcftab_state_xlate(uint32_t state); 235 static uint32_t emlxs_fcftab_event(emlxs_port_t *port, 236 uint32_t evt, void *arg1); 237 238 /* 239 * - Online sequencing can start from FCFI_STATE_OFFLINE state 240 * 241 * - Offline sequencing can interrupt the online sequencing at the 242 * entry of the next wait state. 243 * 244 * NORMAL ONLINE SEQ 245 * --------------------------- 246 * LINK_UP event <-- Adapter 247 * FCFTAB_STATE_OFFLINE 248 * FCFTAB_STATE_SOLICIT 249 * FCFTAB_STATE_SOLICIT_CMPL 250 * FCFTAB_STATE_READ 251 * FCFTAB_STATE_READ_CMPL 252 * FCFTAB_STATE_FCFI_OFFLINE 253 * FCFTAB_STATE_FCFI_OFFLINE_CMPL 254 * FCFTAB_STATE_FCFI_ONLINE 255 * FCFTAB_STATE_FCFI_ONLINE_CMPL 256 * FCFTAB_STATE_ONLINE 257 * 258 * 259 * NORMAL OFFLINE SEQ 260 * --------------------------- 261 * LINK_DOWN event <-- Adapter 262 * FCFTAB_STATE_ONLINE 263 * FCFTAB_STATE_FCFI_OFFLINE 264 * FCFTAB_STATE_FCFI_OFFLINE_CMPL 265 * FCFTAB_STATE_OFFLINE 266 * 267 */ 268 /* Order does matter */ 269 static void *emlxs_fcftab_action_table[] = 270 { 271 /* Action routine Event */ 272 /* FCFTAB_STATE_SHUTDOWN 0 (Requires adapter reset) */ 273 (void *) emlxs_fcftab_shutdown_action, /* STATE_ENTER */ 274 (void *) NULL, /* SHUTDOWN */ 275 (void *) NULL, /* LINK_UP */ 276 (void *) NULL, /* LINK_DOWN */ 277 (void *) NULL, /* CVL_RECD */ 278 (void *) NULL, /* FCF_FOUND */ 279 (void *) NULL, /* FCF_LOST */ 280 (void *) NULL, /* FCF_CHANGED */ 281 (void *) NULL, /* TABLE_FULL */ 282 (void *) NULL, /* FCFI_ONLINE */ 283 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 284 285 /* FCFTAB_STATE_OFFLINE 1 (Wait for LINK_UP event) */ 286 (void *) emlxs_fcftab_offline_action, /* STATE_ENTER */ 287 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 288 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 289 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 290 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 291 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 292 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 293 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 294 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 295 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 296 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 297 298 299 /* FCFTAB_STATE_SOLICIT 2 (Wait on fcf_solicit cmpl) */ 300 (void *) emlxs_fcftab_sol_action, /* STATE_ENTER */ 301 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 302 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 303 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 304 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 305 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 306 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 307 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 308 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 309 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 310 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 311 312 /* FCFTAB_STATE_SOLICIT_FAILED 3 (Transitional) */ 313 (void *) emlxs_fcftab_sol_failed_action, /* STATE_ENTER */ 314 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 315 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 316 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 317 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 318 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 319 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 320 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 321 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 322 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 323 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 324 325 /* FCFTAB_STATE_SOLICIT_CMPL 4 (Wait on fcf timer cmpl) */ 326 (void *) emlxs_fcftab_sol_cmpl_action, /* STATE_ENTER */ 327 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 328 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 329 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 330 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 331 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 332 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 333 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 334 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 335 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 336 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 337 338 339 /* FCFTAB_STATE_READ 5 (Wait on fcf_read cmpl) */ 340 (void *) emlxs_fcftab_read_action, /* STATE_ENTER */ 341 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 342 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 343 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 344 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 345 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 346 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 347 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 348 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 349 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 350 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 351 352 /* FCFTAB_STATE_READ_FAILED 6 (Transitional) */ 353 (void *) emlxs_fcftab_read_failed_action, /* STATE_ENTER */ 354 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 355 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 356 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 357 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 358 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 359 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 360 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 361 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 362 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 363 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 364 365 /* FCFTAB_STATE_READ_CMPL 7 (Transitional) */ 366 (void *) emlxs_fcftab_read_cmpl_action, /* STATE_ENTER */ 367 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 368 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 369 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 370 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 371 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 372 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 373 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 374 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 375 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 376 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 377 378 379 /* FCFTAB_STATE_FCFI_OFFLINE_CMPL 8 (Transitional) */ 380 (void *) emlxs_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */ 381 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 382 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 383 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 384 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 385 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 386 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 387 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 388 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 389 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 390 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 391 392 /* FCFTAB_STATE_FCFI_OFFLINE 9 (Wait for FCFI_OFFLINE event) */ 393 (void *) emlxs_fcftab_fcfi_offline_action, /* STATE_ENTER */ 394 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 395 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 396 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 397 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 398 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 399 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 400 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 401 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 402 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 403 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 404 405 406 /* FCFTAB_STATE_FCFI_ONLINE 10 (Wait on FCFI_ONLINE event) */ 407 (void *) emlxs_fcftab_fcfi_online_action, /* STATE_ENTER */ 408 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 409 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 410 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 411 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 412 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 413 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 414 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 415 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 416 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 417 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 418 419 /* FCFTAB_STATE_FCFI_ONLINE_CMPL 11 (Transitional) */ 420 (void *) emlxs_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */ 421 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 422 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 423 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 424 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 425 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 426 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 427 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 428 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 429 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 430 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 431 432 433 /* FCFTAB_STATE_ONLINE 12 (Wait for LINK_DOWN event) */ 434 (void *) emlxs_fcftab_online_action, /* STATE_ENTER */ 435 (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ 436 (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ 437 (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ 438 (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ 439 (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ 440 (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ 441 (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ 442 (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ 443 (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ 444 (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 445 446 }; /* emlxs_fcftab_action_table[] */ 447 #define FCFTAB_ACTION_EVENTS 11 448 #define FCFTAB_ACTION_STATES \ 449 (sizeof (emlxs_fcftab_action_table)/ \ 450 (FCFTAB_ACTION_EVENTS * sizeof (void *))) 451 452 453 /* ********************************************************************** */ 454 /* VFTAB - This will be needed for multi-virtual fabric environments */ 455 /* ********************************************************************** */ 456 457 /* Order does not matter */ 458 emlxs_table_t emlxs_vftab_state_table[] = 459 { 460 {VFTAB_STATE_DISABLED, "VFTAB_STATE_DISABLED"}, 461 462 }; /* emlxs_vftab_state_table */ 463 464 465 466 /* ********************************************************************** */ 467 /* FCFI */ 468 /* ********************************************************************** */ 469 470 /* Order does not matter */ 471 emlxs_table_t emlxs_fcfi_state_table[] = 472 { 473 {FCFI_STATE_FREE, "FCFI_STATE_FREE"}, 474 475 {FCFI_STATE_OFFLINE, "FCFI_STATE_OFFLINE"}, 476 477 {FCFI_STATE_UNREG_CMPL, "FCFI_STATE_UNREG_CMPL"}, 478 {FCFI_STATE_UNREG_FAILED, "FCFI_STATE_UNREG_FAILED"}, 479 {FCFI_STATE_UNREG, "FCFI_STATE_UNREG"}, 480 481 {FCFI_STATE_REG, "FCFI_STATE_REG"}, 482 {FCFI_STATE_REG_FAILED, "FCFI_STATE_REG_FAILED"}, 483 {FCFI_STATE_REG_CMPL, "FCFI_STATE_REG_CMPL"}, 484 485 {FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_STATE_VFI_OFFLINE_CMPL"}, 486 {FCFI_STATE_VFI_OFFLINE, "FCFI_STATE_VFI_OFFLINE"}, 487 488 {FCFI_STATE_VFI_ONLINE, "FCFI_STATE_VFI_ONLINE"}, 489 {FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_STATE_VFI_ONLINE_CMPL"}, 490 491 {FCFI_STATE_PAUSED, "FCFI_STATE_PAUSED"}, 492 {FCFI_STATE_ONLINE, "FCFI_STATE_ONLINE"}, 493 494 }; /* emlxs_fcfi_state_table */ 495 496 497 static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port, 498 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 499 static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port, 500 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 501 static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port, 502 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 503 static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port, 504 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 505 static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port, 506 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 507 static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port, 508 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 509 static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, 510 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 511 static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, 512 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 513 static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port, 514 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 515 static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, 516 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 517 static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port, 518 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 519 static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, 520 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 521 static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, 522 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 523 static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, 524 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 525 static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port, 526 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 527 static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port, 528 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 529 static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port, 530 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 531 static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, 532 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 533 static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, 534 FCFIobj_t *fcfp, uint32_t evt, void *arg1); 535 536 static uint32_t emlxs_fcfi_event(emlxs_port_t *port, 537 uint32_t evt, void *arg1); 538 static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, 539 uint32_t *fcf_index); 540 static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port); 541 static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp); 542 static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, 543 FCF_RECORD_t *fcf_rec, uint32_t event_tag); 544 static char *emlxs_fcfi_state_xlate(uint32_t state); 545 546 /* 547 * - Online sequencing can start from FCFI_STATE_OFFLINE state or 548 * the FCFI_STATE_VFI_OFFLINE state. 549 * 550 * - Offline sequencing can interrupt the online sequencing at the 551 * entry of the next wait state. 552 * 553 * NORMAL ONLINE SEQ 554 * --------------------------- 555 * FCFI_ONLINE event <-- FCFTAB 556 * FCFI_STATE_OFFLINE 557 * FCFI_STATE_REG 558 * FCFI_STATE_REG_CMPL 559 * FCFI_STATE_VFI_ONLINE 560 * FCFI_STATE_VFI_ONLINE_CMPL 561 * FCFI_STATE_ONLINE 562 * FCFI_ONLINE event-->FCFTAB 563 * 564 * 565 * NORMAL OFFLINE SEQ 566 * --------------------------- 567 * FCFI_OFFLINE event <-- FCFTAB 568 * FCFI_STATE_ONLINE 569 * FCFI_STATE_VFI_OFFLINE 570 * FCFI_STATE_VFI_OFFLINE_CMPL 571 * FCFI_STATE_UNREG 572 * FCFI_STATE_UNREG_CMPL 573 * FCFI_STATE_OFFLINE 574 * FCFI_OFFLINE event-->FCFTAB 575 * 576 * 577 * NORMAL PAUSE SEQ 578 * --------------------------- 579 * FCFI_PAUSE event <-- FCFTAB 580 * FCFI_STATE_ONLINE 581 * FCFI_STATE_PAUSED 582 * 583 */ 584 /* Order does matter */ 585 static void *emlxs_fcfi_action_table[] = 586 { 587 /* Action routine Event */ 588 /* FCFI_STATE_FREE 0 (Wait for allocation) */ 589 (void *) emlxs_fcfi_free_action, /* STATE_ENTER */ 590 (void *) NULL, /* FCFI_ONLINE */ 591 (void *) NULL, /* FCFI_OFFLINE */ 592 (void *) NULL, /* FCFI_PAUSE */ 593 (void *) NULL, /* VFI_ONLINE */ 594 (void *) NULL, /* VFI_OFFLINE */ 595 596 /* FCFI_STATE_OFFLINE 1 (Wait for FCFI_ONLINE event) */ 597 (void *) emlxs_fcfi_offline_action, /* STATE_ENTER */ 598 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 599 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 600 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 601 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 602 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 603 604 /* FCFI_STATE_UNREG_CMPL 2 (Transitional) */ 605 (void *) emlxs_fcfi_unreg_cmpl_action, /* STATE_ENTER */ 606 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 607 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 608 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 609 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 610 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 611 612 /* FCFI_STATE_UNREG_FAILED 3 (Transitional) */ 613 (void *) emlxs_fcfi_unreg_failed_action, /* STATE_ENTER */ 614 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 615 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 616 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 617 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 618 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 619 620 /* FCFI_STATE_UNREG 4 (Wait for unreg_fcfi cmpl) */ 621 (void *) emlxs_fcfi_unreg_action, /* STATE_ENTER */ 622 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 623 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 624 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 625 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 626 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 627 628 /* FCFI_STATE_REG 5 (Wait for reg_fcfi cmpl) */ 629 (void *) emlxs_fcfi_reg_action, /* STATE_ENTER */ 630 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 631 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 632 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 633 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 634 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 635 636 /* FCFI_STATE_REG_FAILED 6 (Transitional) */ 637 (void *) emlxs_fcfi_reg_failed_action, /* STATE_ENTER */ 638 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 639 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 640 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 641 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 642 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 643 644 /* FCFI_STATE_REG_CMPL 7 (Transitional) */ 645 (void *) emlxs_fcfi_reg_cmpl_action, /* STATE_ENTER */ 646 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 647 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 648 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 649 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 650 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 651 652 /* FCFI_STATE_VFI_OFFLINE_CMPL 8 (Transitional) */ 653 (void *) emlxs_fcfi_vfi_offline_cmpl_action, /* STATE_ENTER */ 654 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 655 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 656 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 657 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 658 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 659 660 /* FCFI_STATE_VFI_OFFLINE 9 (Wait for VFI_OFFLINE event) */ 661 (void *) emlxs_fcfi_vfi_offline_action, /* STATE_ENTER */ 662 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 663 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 664 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 665 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 666 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE * */ 667 668 /* FCFI_STATE_VFI_ONLINE 10 (Wait for VFI_ONLINE event) */ 669 (void *) emlxs_fcfi_vfi_online_action, /* STATE_ENTER */ 670 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 671 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 672 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 673 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 674 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 675 676 /* FCFI_STATE_VFI_ONLINE_CMPL 11 (Transitional) */ 677 (void *) emlxs_fcfi_vfi_online_cmpl_action, /* STATE_ENTER */ 678 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 679 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 680 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 681 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 682 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 683 684 685 /* FCFI_STATE_PAUSED 12 (Wait for FCFI_ONLINE event) */ 686 (void *) emlxs_fcfi_paused_action, /* STATE_ENTER */ 687 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 688 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 689 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 690 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 691 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 692 693 /* FCFI_STATE_ONLINE 13 (Wait for FCFI_OFFLINE event) */ 694 (void *) emlxs_fcfi_online_action, /* STATE_ENTER */ 695 (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ 696 (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ 697 (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ 698 (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ 699 (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ 700 701 }; /* emlxs_fcfi_action_table[] */ 702 #define FCFI_ACTION_EVENTS 6 703 #define FCFI_ACTION_STATES \ 704 (sizeof (emlxs_fcfi_action_table)/ \ 705 (FCFI_ACTION_EVENTS * sizeof (void *))) 706 707 708 /* ********************************************************************** */ 709 /* VFI */ 710 /* ********************************************************************** */ 711 712 /* Order does not matter */ 713 emlxs_table_t emlxs_vfi_state_table[] = 714 { 715 {VFI_STATE_OFFLINE, "VFI_STATE_OFFLINE"}, 716 717 {VFI_STATE_INIT, "VFI_STATE_INIT"}, 718 {VFI_STATE_INIT_FAILED, "VFI_STATE_INIT_FAILED"}, 719 {VFI_STATE_INIT_CMPL, "VFI_STATE_INIT_CMPL"}, 720 721 {VFI_STATE_VPI_OFFLINE_CMPL, "VFI_STATE_VPI_OFFLINE_CMPL"}, 722 {VFI_STATE_VPI_OFFLINE, "VFI_STATE_VPI_OFFLINE"}, 723 724 {VFI_STATE_VPI_ONLINE, "VFI_STATE_VPI_ONLINE"}, 725 {VFI_STATE_VPI_ONLINE_CMPL, "VFI_STATE_VPI_ONLINE_CMPL"}, 726 727 {VFI_STATE_UNREG_CMPL, "VFI_STATE_UNREG_CMPL"}, 728 {VFI_STATE_UNREG_FAILED, "VFI_STATE_UNREG_FAILED"}, 729 {VFI_STATE_UNREG, "VFI_STATE_UNREG"}, 730 731 {VFI_STATE_REG, "VFI_STATE_REG"}, 732 {VFI_STATE_REG_FAILED, "VFI_STATE_REG_FAILED"}, 733 {VFI_STATE_REG_CMPL, "VFI_STATE_REG_CMPL"}, 734 735 {VFI_STATE_PAUSED, "VFI_STATE_PAUSED"}, 736 {VFI_STATE_ONLINE, "VFI_STATE_ONLINE"}, 737 738 }; /* emlxs_vfi_state_table */ 739 740 741 static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port, 742 VFIobj_t *vfip, uint32_t evt, void *arg1); 743 static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port, 744 VFIobj_t *vfip, uint32_t evt, void *arg1); 745 static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port, 746 VFIobj_t *vfip, uint32_t evt, void *arg1); 747 static uint32_t emlxs_vfi_init_action(emlxs_port_t *port, 748 VFIobj_t *vfip, uint32_t evt, void *arg1); 749 static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port, 750 VFIobj_t *vfip, uint32_t evt, void *arg1); 751 static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port, 752 VFIobj_t *vfip, uint32_t evt, void *arg1); 753 static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port, 754 VFIobj_t *vfip, uint32_t evt, void *arg1); 755 static uint32_t emlxs_vfi_online_action(emlxs_port_t *port, 756 VFIobj_t *vfip, uint32_t evt, void *arg1); 757 static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port, 758 VFIobj_t *vfip, uint32_t evt, void *arg1); 759 static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port, 760 VFIobj_t *vfip, uint32_t evt, void *arg1); 761 static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, 762 VFIobj_t *vfip, uint32_t evt, void *arg1); 763 static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port, 764 VFIobj_t *vfip, uint32_t evt, void *arg1); 765 static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, 766 VFIobj_t *vfip, uint32_t evt, void *arg1); 767 static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port, 768 VFIobj_t *vfip, uint32_t evt, void *arg1); 769 static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port, 770 VFIobj_t *vfip, uint32_t evt, void *arg1); 771 static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, 772 VFIobj_t *vfip, uint32_t evt, void *arg1); 773 static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port, 774 VFIobj_t *vfip, uint32_t evt, void *arg1); 775 static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port, 776 VFIobj_t *vfip, uint32_t evt, void *arg1); 777 static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, 778 VFIobj_t *vfip, uint32_t evt, void *arg1); 779 static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, 780 VFIobj_t *vfip, uint32_t evt, void *arg1); 781 static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, 782 VFIobj_t *vfip, uint32_t evt, void *arg1); 783 784 static uint32_t emlxs_vfi_event(emlxs_port_t *port, 785 uint32_t evt, void *arg1); 786 787 788 /* 789 * - Online sequencing can start from VFI_STATE_OFFLINE state or 790 * the VFI_STATE_VPI_OFFLINE state. 791 * 792 * - Offline sequencing can interrupt the online sequencing at the 793 * entry of the next wait state. 794 * 795 * NORMAL ONLINE SEQ 796 * --------------------------- 797 * VFI_ONLINE event <-- FCFI 798 * VFI_STATE_OFFLINE 799 * VFI_STATE_INIT 800 * VFI_STATE_INIT_CMPL 801 * VFI_STATE_VPI_ONLINE 802 * VFI_STATE_VPI_ONLINE_CMPL 803 * VFI_STATE_REG 804 * VFI_STATE_REG_CMPL 805 * VFI_STATE_ONLINE 806 * VFI_ONLINE event-->FCFI 807 * 808 * 809 * NORMAL OFFLINE SEQ 810 * --------------------------- 811 * VFI_OFFLINE event <-- FCFI 812 * VFI_STATE_ONLINE 813 * VFI_STATE_VPI_OFFLINE 814 * VFI_STATE_VPI_OFFLINE_CMPL 815 * VFI_STATE_UNREG 816 * VFI_STATE_UNREG_CMPL 817 * VFI_STATE_OFFLINE 818 * VFI_OFFLINE event-->FCFI 819 * 820 * 821 * NORMAL PAUSE SEQ 822 * --------------------------- 823 * VFI_PAUSE event <-- FCFI 824 * VFI_STATE_ONLINE 825 * VFI_STATE_PAUSED 826 * 827 */ 828 /* Order does matter */ 829 static void *emlxs_vfi_action_table[] = 830 { 831 /* Action routine Event */ 832 /* VFI_STATE_OFFLINE 0 (Wait for VFI_ONLINE event) */ 833 (void *) emlxs_vfi_offline_action, /* STATE_ENTER */ 834 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 835 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 836 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 837 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 838 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 839 840 841 /* VFI_STATE_INIT 1 (Wait for init_vfi cmpl) */ 842 (void *) emlxs_vfi_init_action, /* STATE_ENTER */ 843 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 844 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 845 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 846 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 847 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 848 849 /* VFI_STATE_INIT_FAILED 2 (Transitional) */ 850 (void *) emlxs_vfi_init_failed_action, /* STATE_ENTER */ 851 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 852 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 853 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 854 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 855 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 856 857 /* VFI_STATE_INIT_CMPL 3 (Transitional) */ 858 (void *) emlxs_vfi_init_cmpl_action, /* STATE_ENTER */ 859 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 860 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 861 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 862 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 863 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 864 865 866 /* VFI_STATE_VPI_OFFLINE_CMPL 4 (Wait for VPI_OFFLINE event) */ 867 (void *) emlxs_vfi_vpi_offline_cmpl_action, /* STATE_ENTER */ 868 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 869 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 870 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 871 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 872 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 873 874 /* VFI_STATE_VPI_OFFLINE 5 (Wait for VPI_OFFLINE event) */ 875 (void *) emlxs_vfi_vpi_offline_action, /* STATE_ENTER */ 876 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 877 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 878 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 879 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 880 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 881 882 883 /* VFI_STATE_VPI_ONLINE 6 (Wait for VPI_ONLINE event) */ 884 (void *) emlxs_vfi_vpi_online_action, /* STATE_ENTER */ 885 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 886 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 887 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 888 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 889 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 890 891 /* VFI_STATE_VPI_ONLINE_CMPL 7 (Transitional) */ 892 (void *) emlxs_vfi_vpi_online_cmpl_action, /* STATE_ENTER */ 893 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 894 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 895 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 896 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 897 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 898 899 900 /* VFI_STATE_UNREG_CMPL 8 (Transitional) */ 901 (void *) emlxs_vfi_unreg_cmpl_action, /* STATE_ENTER */ 902 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 903 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 904 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 905 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 906 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 907 908 /* VFI_STATE_UNREG_FAILED 9 (Transitional) */ 909 (void *) emlxs_vfi_unreg_failed_action, /* STATE_ENTER */ 910 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 911 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 912 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 913 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 914 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 915 916 /* VFI_STATE_UNREG 10 (Wait for unreg_vfi cmpl) */ 917 (void *) emlxs_vfi_unreg_action, /* STATE_ENTER */ 918 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 919 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 920 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 921 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 922 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 923 924 925 /* VFI_STATE_REG 11 (Wait for reg_vfi cmpl) */ 926 (void *) emlxs_vfi_reg_action, /* STATE_ENTER */ 927 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 928 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 929 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 930 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 931 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 932 933 /* VFI_STATE_REG_FAILED 12 (Transitional) */ 934 (void *) emlxs_vfi_reg_failed_action, /* STATE_ENTER */ 935 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 936 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 937 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 938 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 939 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 940 941 /* VFI_STATE_REG_CMPL 13 (Transitional) */ 942 (void *) emlxs_vfi_reg_cmpl_action, /* STATE_ENTER */ 943 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 944 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 945 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 946 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 947 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 948 949 950 /* VFI_STATE_PAUSED 14 (Wait for VFI_OFFLINE event) */ 951 (void *) emlxs_vfi_paused_action, /* STATE_ENTER */ 952 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 953 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 954 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 955 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 956 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 957 958 /* VFI_STATE_ONLINE 14 (Wait for VFI_OFFLINE event) */ 959 (void *) emlxs_vfi_online_action, /* STATE_ENTER */ 960 (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ 961 (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ 962 (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ 963 (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ 964 (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ 965 966 }; /* emlxs_vfi_action_table[] */ 967 #define VFI_ACTION_EVENTS 6 968 #define VFI_ACTION_STATES \ 969 (sizeof (emlxs_vfi_action_table)/ \ 970 (VFI_ACTION_EVENTS * sizeof (void *))) 971 972 973 /* ********************************************************************** */ 974 /* VPI */ 975 /* ********************************************************************** */ 976 977 /* Order does not matter */ 978 emlxs_table_t emlxs_vpi_state_table[] = 979 { 980 {VPI_STATE_OFFLINE, "VPI_STATE_OFFLINE"}, 981 982 {VPI_STATE_INIT, "VPI_STATE_INIT"}, 983 {VPI_STATE_INIT_FAILED, "VPI_STATE_INIT_FAILED"}, 984 {VPI_STATE_INIT_CMPL, "VPI_STATE_INIT_CMPL"}, 985 986 {VPI_STATE_UNREG_CMPL, "VPI_STATE_UNREG_CMPL"}, 987 {VPI_STATE_UNREG_FAILED, "VPI_STATE_UNREG_FAILED"}, 988 {VPI_STATE_UNREG, "VPI_STATE_UNREG"}, 989 990 {VPI_STATE_LOGO_CMPL, "VPI_STATE_LOGO_CMPL"}, 991 {VPI_STATE_LOGO_FAILED, "VPI_STATE_LOGO_FAILED"}, 992 {VPI_STATE_LOGO, "VPI_STATE_LOGO"}, 993 994 {VPI_STATE_PORT_OFFLINE, "VPI_STATE_PORT_OFFLINE"}, 995 {VPI_STATE_PORT_ONLINE, "VPI_STATE_PORT_ONLINE"}, 996 997 {VPI_STATE_LOGI, "VPI_STATE_LOGI"}, 998 {VPI_STATE_LOGI_FAILED, "VPI_STATE_LOGI_FAILED"}, 999 {VPI_STATE_LOGI_CMPL, "VPI_STATE_LOGI_CMPL"}, 1000 1001 {VPI_STATE_REG, "VPI_STATE_REG"}, 1002 {VPI_STATE_REG_FAILED, "VPI_STATE_REG_FAILED"}, 1003 {VPI_STATE_REG_CMPL, "VPI_STATE_REG_CMPL"}, 1004 1005 {VPI_STATE_PAUSED, "VPI_STATE_PAUSED"}, 1006 {VPI_STATE_ONLINE, "VPI_STATE_ONLINE"}, 1007 1008 }; /* emlxs_vpi_state_table */ 1009 1010 1011 static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port, 1012 VPIobj_t *vpip, uint32_t evt, void *arg1); 1013 static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port, 1014 VPIobj_t *vpip, uint32_t evt, void *arg1); 1015 static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port, 1016 VPIobj_t *vpip, uint32_t evt, void *arg1); 1017 static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, 1018 VPIobj_t *vpip, uint32_t evt, void *arg1); 1019 static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, 1020 VPIobj_t *vpip, uint32_t evt, void *arg1); 1021 static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, 1022 VPIobj_t *vpip, uint32_t evt, void *arg1); 1023 1024 static uint32_t emlxs_vpi_init_action(emlxs_port_t *port, 1025 VPIobj_t *vpip, uint32_t evt, void *arg1); 1026 static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port, 1027 VPIobj_t *vpip, uint32_t evt, void *arg1); 1028 static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port, 1029 VPIobj_t *vpip, uint32_t evt, void *arg1); 1030 1031 static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port, 1032 VPIobj_t *vpip, uint32_t evt, void *arg1); 1033 static uint32_t emlxs_vpi_online_action(emlxs_port_t *port, 1034 VPIobj_t *vpip, uint32_t evt, void *arg1); 1035 static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port, 1036 VPIobj_t *vpip, uint32_t evt, void *arg1); 1037 1038 static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port, 1039 VPIobj_t *vpip, uint32_t evt, void *arg1); 1040 static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port, 1041 VPIobj_t *vpip, uint32_t evt, void *arg1); 1042 1043 static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, 1044 VPIobj_t *vpip, uint32_t evt, void *arg1); 1045 static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port, 1046 VPIobj_t *vpip, uint32_t evt, void *arg1); 1047 static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port, 1048 VPIobj_t *vpip, uint32_t evt, void *arg1); 1049 1050 static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port, 1051 VPIobj_t *vpip, uint32_t evt, void *arg1); 1052 static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port, 1053 VPIobj_t *vpip, uint32_t evt, void *arg1); 1054 static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, 1055 VPIobj_t *vpip, uint32_t evt, void *arg1); 1056 1057 static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port, 1058 VPIobj_t *vpip, uint32_t evt, void *arg1); 1059 static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port, 1060 VPIobj_t *vpip, uint32_t evt, void *arg1); 1061 static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, 1062 VPIobj_t *vpip, uint32_t evt, void *arg1); 1063 1064 static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port, 1065 VPIobj_t *vpip, uint32_t evt, void *arg1); 1066 static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port, 1067 VPIobj_t *vpip, uint32_t evt, void *arg1); 1068 static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, 1069 VPIobj_t *vpip, uint32_t evt, void *arg1); 1070 1071 static uint32_t emlxs_vpi_event(emlxs_port_t *port, 1072 uint32_t evt, void *arg1); 1073 static void emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip, 1074 uint32_t status); 1075 1076 /* 1077 * - Online sequencing can only start from VPI_STATE_OFFLINE or 1078 * VPI_STATE_PORT_OFFLINE state. 1079 * 1080 * - Offline sequencing can interrupt the online sequencing at the 1081 * entry of the next wait state. 1082 * 1083 * NORMAL ONLINE SEQ 1084 * --------------------------- 1085 * VPI_ONLINE event <-- VFI 1086 * VPI_STATE_OFFLINE 1087 * VPI_STATE_INIT 1088 * VPI_STATE_INIT_CMPL 1089 * VPI_STATE_PORT_ONLINE 1090 * VPI_STATE_LOGI 1091 * VPI_STATE_LOGI_CMPL 1092 * VPI_STATE_REG 1093 * VPI_STATE_REG_CMPL 1094 * VPI_STATE_ONLINE 1095 * VPI_ONLINE event-->VFI 1096 * 1097 * 1098 * NORMAL OFFLINE SEQ 1099 * --------------------------- 1100 * VPI_OFFLINE event <-- VFI 1101 * VPI_STATE_ONLINE 1102 * VPI_STATE_PORT_OFFLINE 1103 * VPI_STATE_LOGO 1104 * VPI_STATE_LOGO_CMPL 1105 * VPI_STATE_UNREG 1106 * VPI_STATE_UNREG_CMPL 1107 * VPI_STATE_OFFLINE 1108 * VPI_OFFLINE event-->VFI 1109 * 1110 * 1111 * NORMAL PAUSE SEQ 1112 * --------------------------- 1113 * VPI_PAUSE event <-- VFI 1114 * VPI_STATE_ONLINE 1115 * VPI_STATE_PORT_OFFLINE 1116 * VPI_STATE_PAUSED 1117 * 1118 */ 1119 /* Order does matter */ 1120 static void *emlxs_vpi_action_table[] = 1121 { 1122 /* Action routine Event */ 1123 /* VPI_STATE_OFFLINE 0 (Wait for VPI_ONLINE event) */ 1124 (void *) emlxs_vpi_offline_action, /* STATE_ENTER */ 1125 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1126 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1127 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1128 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1129 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1130 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1131 1132 1133 /* VPI_STATE_INIT 1 (Wait for init_vpi cmpl) */ 1134 (void *) emlxs_vpi_init_action, /* STATE_ENTER */ 1135 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1136 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1137 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1138 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1139 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1140 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1141 1142 /* VPI_STATE_INIT_FAILED 2 (Transitional) */ 1143 (void *) emlxs_vpi_init_failed_action, /* STATE_ENTER */ 1144 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1145 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1146 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1147 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1148 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1149 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1150 1151 /* VPI_STATE_INIT_CMPL 3 (Transitional) */ 1152 (void *) emlxs_vpi_init_cmpl_action, /* STATE_ENTER */ 1153 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1154 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1155 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1156 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1157 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1158 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1159 1160 1161 /* VPI_STATE_UNREG_CMPL 4 (Transitional) */ 1162 (void *) emlxs_vpi_unreg_cmpl_action, /* STATE_ENTER */ 1163 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1164 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1165 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1166 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1167 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1168 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1169 1170 /* VPI_STATE_UNREG_FAILED 5 (Transitional) */ 1171 (void *) emlxs_vpi_unreg_failed_action, /* STATE_ENTER */ 1172 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1173 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1174 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1175 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1176 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1177 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1178 1179 /* VPI_STATE_UNREG 6 (Wait for unreg_vpi cmpl) */ 1180 (void *) emlxs_vpi_unreg_action, /* STATE_ENTER */ 1181 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1182 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1183 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1184 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1185 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1186 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1187 1188 1189 /* VPI_STATE_LOGO_CMPL 7 (Transitional) */ 1190 (void *) emlxs_vpi_logo_cmpl_action, /* STATE_ENTER */ 1191 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1192 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1193 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1194 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1195 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1196 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1197 1198 /* VPI_STATE_LOGO_FAILED 8 (Transitional) */ 1199 (void *) emlxs_vpi_logo_failed_action, /* STATE_ENTER */ 1200 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1201 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1202 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1203 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1204 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1205 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1206 1207 /* VPI_STATE_LOGO 9 (Transitional) */ 1208 (void *) emlxs_vpi_logo_action, /* STATE_ENTER */ 1209 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1210 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1211 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1212 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1213 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1214 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1215 1216 1217 /* VPI_STATE_PORT_OFFLINE 10 (Wait for RPI_OFFLINE or VPI_ONLINE) */ 1218 (void *) emlxs_vpi_port_offline_action, /* STATE_ENTER */ 1219 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1220 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1221 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1222 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1223 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1224 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1225 1226 /* VPI_STATE_PORT_ONLINE 11 (Wait for emlxs_vpi_logi_notify() ) */ 1227 (void *) emlxs_vpi_port_online_action, /* STATE_ENTER */ 1228 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1229 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1230 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1231 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1232 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1233 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1234 1235 1236 /* VPI_STATE_LOGI 12 (Wait for emlxs_vpi_logi_cmpl_notify() ) */ 1237 (void *) emlxs_vpi_logi_action, /* STATE_ENTER */ 1238 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1239 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1240 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1241 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1242 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1243 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1244 1245 /* VPI_STATE_LOGI_FAILED 13 (Transitional) */ 1246 (void *) emlxs_vpi_logi_failed_action, /* STATE_ENTER */ 1247 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1248 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1249 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1250 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1251 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1252 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1253 1254 /* VPI_STATE_LOGI_CMPL 14 (Transitional) */ 1255 (void *) emlxs_vpi_logi_cmpl_action, /* STATE_ENTER */ 1256 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1257 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1258 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1259 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1260 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1261 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1262 1263 1264 /* VPI_STATE_REG 15 (Wait for reg_vpi cmpl) */ 1265 (void *) emlxs_vpi_reg_action, /* STATE_ENTER */ 1266 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1267 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1268 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1269 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1270 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1271 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1272 1273 /* VPI_STATE_REG_FAILED 16 (Transitional) */ 1274 (void *) emlxs_vpi_reg_failed_action, /* STATE_ENTER */ 1275 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1276 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1277 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1278 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1279 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1280 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1281 1282 /* VPI_STATE_REG_CMPL 17 (Transitional) */ 1283 (void *) emlxs_vpi_reg_cmpl_action, /* STATE_ENTER */ 1284 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1285 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1286 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1287 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1288 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1289 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1290 1291 1292 /* VPI_STATE_PAUSED 18 (Wait for VPI_ONLINE() ) */ 1293 (void *) emlxs_vpi_paused_action, /* STATE_ENTER */ 1294 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1295 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1296 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1297 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1298 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1299 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1300 1301 /* VPI_STATE_ONLINE 19 (Wait for VPI_OFFLINE event) */ 1302 (void *) emlxs_vpi_online_action, /* STATE_ENTER */ 1303 (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ 1304 (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ 1305 (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ 1306 (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ 1307 (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ 1308 (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ 1309 1310 }; /* emlxs_vpi_action_table() */ 1311 #define VPI_ACTION_EVENTS 7 1312 #define VPI_ACTION_STATES \ 1313 (sizeof (emlxs_vpi_action_table)/ \ 1314 (VPI_ACTION_EVENTS * sizeof (void *))) 1315 1316 1317 /* ********************************************************************** */ 1318 /* RPI */ 1319 /* ********************************************************************** */ 1320 1321 /* Order does not matter */ 1322 emlxs_table_t emlxs_rpi_state_table[] = 1323 { 1324 {RPI_STATE_FREE, "RPI_STATE_FREE"}, 1325 1326 {RPI_STATE_OFFLINE, "RPI_STATE_OFFLINE"}, 1327 1328 {RPI_STATE_UNREG_CMPL, "RPI_STATE_UNREG_CMPL"}, 1329 {RPI_STATE_UNREG_FAILED, "RPI_STATE_UNREG_FAILED"}, 1330 {RPI_STATE_UNREG, "RPI_STATE_UNREG"}, 1331 1332 {RPI_STATE_REG, "RPI_STATE_REG"}, 1333 {RPI_STATE_REG_FAILED, "RPI_STATE_REG_FAILED"}, 1334 {RPI_STATE_REG_CMPL, "RPI_STATE_REG_CMPL"}, 1335 1336 {RPI_STATE_PAUSED, "RPI_STATE_PAUSED"}, 1337 1338 {RPI_STATE_RESUME, "RPI_STATE_RESUME"}, 1339 {RPI_STATE_RESUME_FAILED, "RPI_STATE_RESUME_FAILED"}, 1340 {RPI_STATE_RESUME_CMPL, "RPI_STATE_RESUME_CMPL"}, 1341 1342 {RPI_STATE_ONLINE, "RPI_STATE_ONLINE"}, 1343 1344 }; /* emlxs_rpi_state_table */ 1345 1346 static uint32_t emlxs_rpi_free_action(emlxs_port_t *port, 1347 RPIobj_t *rpip, uint32_t evt, void *arg1); 1348 1349 static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port, 1350 RPIobj_t *rpip, uint32_t evt, void *arg1); 1351 static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port, 1352 RPIobj_t *rpip, uint32_t evt, void *arg1); 1353 static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port, 1354 RPIobj_t *rpip, uint32_t evt, void *arg1); 1355 static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port, 1356 RPIobj_t *rpip, uint32_t evt, void *arg1); 1357 1358 static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port, 1359 RPIobj_t *rpip, uint32_t evt, void *arg1); 1360 static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, 1361 RPIobj_t *rpip, uint32_t evt, void *arg1); 1362 static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port, 1363 RPIobj_t *rpip, uint32_t evt, void *arg1); 1364 1365 static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port, 1366 RPIobj_t *rpip, uint32_t evt, void *arg1); 1367 static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, 1368 RPIobj_t *rpip, uint32_t evt, void *arg1); 1369 static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port, 1370 RPIobj_t *rpip, uint32_t evt, void *arg1); 1371 1372 static uint32_t emlxs_rpi_online_action(emlxs_port_t *port, 1373 RPIobj_t *rpip, uint32_t evt, void *arg1); 1374 static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port, 1375 RPIobj_t *rpip, uint32_t evt, void *arg1); 1376 static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port, 1377 RPIobj_t *rpip, uint32_t evt, void *arg1); 1378 1379 static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port, 1380 RPIobj_t *rpip, uint32_t evt, void *arg1); 1381 static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, 1382 RPIobj_t *rpip, uint32_t evt, void *arg1); 1383 static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port, 1384 RPIobj_t *rpip, uint32_t evt, void *arg1); 1385 1386 static uint32_t emlxs_rpi_event(emlxs_port_t *port, 1387 uint32_t evt, void *arg1); 1388 static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did); 1389 static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip); 1390 static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did); 1391 1392 static void emlxs_rpi_resume_handler(emlxs_port_t *port, 1393 RPIobj_t *rpip); 1394 static void emlxs_rpi_unreg_handler(emlxs_port_t *port, 1395 RPIobj_t *rpip); 1396 static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port, 1397 RPIobj_t *rpip); 1398 /* 1399 * - Online sequencing can start from RPI_STATE_OFFLINE state or 1400 * the RPI_STATE_PAUSED state. 1401 * 1402 * - Offline sequencing can interrupt the online sequencing at the 1403 * entry of the next wait state. 1404 * 1405 * NORMAL ONLINE SEQ 1406 * --------------------------- 1407 * RPI_ONLINE event <-- VPI 1408 * RPI_STATE_OFFLINE 1409 * RPI_STATE_REG 1410 * RPI_STATE_REG_CMPL 1411 * RPI_STATE_ONLINE 1412 * RPI_ONLINE event-->VPI 1413 * 1414 * 1415 * NORMAL OFFLINE SEQ 1416 * --------------------------- 1417 * RPI_OFFLINE event <-- VPI 1418 * RPI_STATE_ONLINE 1419 * RPI_STATE_UNREG 1420 * RPI_STATE_UNREG_CMPL 1421 * RPI_STATE_OFFLINE 1422 * RPI_OFFLINE event-->VPI 1423 * 1424 * 1425 * NORMAL PAUSE SEQ 1426 * --------------------------- 1427 * RPI_PAUSE event <-- VPI 1428 * RPI_STATE_ONLINE 1429 * RPI_STATE_PAUSED 1430 * 1431 */ 1432 /* Order does matter */ 1433 static void *emlxs_rpi_action_table[] = 1434 { 1435 /* Action routine Event */ 1436 /* RPI_STATE_FREE 0 (Wait for allocation) */ 1437 (void *) emlxs_rpi_free_action, /* STATE_ENTER */ 1438 (void *) NULL, /* RPI_ONLINE */ 1439 (void *) NULL, /* RPI_OFFLINE */ 1440 (void *) NULL, /* RPI_PAUSE */ 1441 (void *) NULL, /* RPI_RESUME */ 1442 1443 /* RPI_STATE_OFFLINE 1 (Wait for RPI_ONLINE event) */ 1444 (void *) emlxs_rpi_offline_action, /* STATE_ENTER */ 1445 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1446 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1447 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1448 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1449 1450 /* RPI_STATE_UNREG_CMPL 2 (Transitional) */ 1451 (void *) emlxs_rpi_unreg_cmpl_action, /* STATE_ENTER */ 1452 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1453 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1454 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1455 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1456 1457 /* RPI_STATE_UNREG_FAILED 3 (Transitional) */ 1458 (void *) emlxs_rpi_unreg_failed_action, /* STATE_ENTER */ 1459 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1460 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1461 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1462 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1463 1464 /* RPI_STATE_UNREG 4 (Wait for unreg_rpi cmpl) */ 1465 (void *) emlxs_rpi_unreg_action, /* STATE_ENTER */ 1466 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1467 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1468 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1469 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1470 1471 1472 /* RPI_STATE_REG 5 (Wait for reg_rpi cmpl) */ 1473 (void *) emlxs_rpi_reg_action, /* STATE_ENTER */ 1474 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1475 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1476 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1477 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1478 1479 /* RPI_STATE_REG_FAILED 6 (Transitional) */ 1480 (void *) emlxs_rpi_reg_failed_action, /* STATE_ENTER */ 1481 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1482 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1483 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1484 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1485 1486 /* RPI_STATE_REG_CMPL 7 (Transitional) */ 1487 (void *) emlxs_rpi_reg_cmpl_action, /* STATE_ENTER */ 1488 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1489 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1490 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1491 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1492 1493 1494 /* RPI_STATE_PAUSED 8 (Wait for RPI_ONLINE) */ 1495 (void *) emlxs_rpi_paused_action, /* STATE_ENTER */ 1496 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1497 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1498 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1499 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1500 1501 1502 /* RPI_STATE_RESUME 9 (Wait for resume_rpi mbcmpl) */ 1503 (void *) emlxs_rpi_resume_action, /* STATE_ENTER */ 1504 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1505 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1506 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1507 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1508 1509 /* RPI_STATE_RESUME_FAILED 10 (Transitional) */ 1510 (void *) emlxs_rpi_resume_failed_action, /* STATE_ENTER */ 1511 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1512 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1513 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1514 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1515 1516 /* RPI_STATE_RESUME_CMPL 11 (Transitional) */ 1517 (void *) emlxs_rpi_resume_cmpl_action, /* STATE_ENTER */ 1518 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1519 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1520 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1521 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1522 1523 1524 /* RPI_STATE_ONLINE 12 (Wait for RPI_OFFLINE event) */ 1525 (void *) emlxs_rpi_online_action, /* STATE_ENTER */ 1526 (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ 1527 (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ 1528 (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ 1529 (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ 1530 1531 }; /* emlxs_rpi_action_table[] */ 1532 #define RPI_ACTION_EVENTS 5 1533 #define RPI_ACTION_STATES \ 1534 (sizeof (emlxs_rpi_action_table)/ \ 1535 (RPI_ACTION_EVENTS * sizeof (void *))) 1536 1537 1538 /* ************************************************************************** */ 1539 /* FCF Generic */ 1540 /* ************************************************************************** */ 1541 1542 extern void 1543 emlxs_fcf_fini(emlxs_hba_t *hba) 1544 { 1545 emlxs_port_t *port = &PPORT; 1546 emlxs_port_t *vport; 1547 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 1548 uint32_t i; 1549 RPIobj_t *rpip; 1550 1551 if (!fcftab->table) { 1552 return; 1553 } 1554 1555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 1556 "emlxs_fcf_fini: %s flag=%x fcfi_online=%d.", 1557 emlxs_fcftab_state_xlate(fcftab->state), 1558 fcftab->flag, fcftab->fcfi_online); 1559 1560 if (fcftab->state != FCFTAB_STATE_SHUTDOWN) { 1561 (void) emlxs_fcf_shutdown_notify(port, 1); 1562 } 1563 1564 mutex_enter(&EMLXS_FCF_LOCK); 1565 1566 /* Free the FCF memory */ 1567 1568 kmem_free(fcftab->table, 1569 (sizeof (FCFIobj_t) * fcftab->table_count)); 1570 1571 fcftab->table = NULL; 1572 fcftab->table_count = 0; 1573 1574 /* Free the VFI memory */ 1575 1576 kmem_free(hba->sli.sli4.VFI_table, 1577 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount)); 1578 1579 hba->sli.sli4.VFI_table = NULL; 1580 hba->sli.sli4.VFICount = 0; 1581 1582 /* Free the VPI Fabric RPI's */ 1583 1584 for (i = 0; i < MAX_VPORTS; i++) { 1585 vport = &VPORT(i); 1586 rpip = &vport->VPIobj.fcf_rpi; 1587 1588 if (rpip->state == RPI_STATE_FREE) { 1589 continue; 1590 } 1591 1592 (void) emlxs_rpi_free(port, rpip); 1593 } 1594 1595 /* Free the RPI memory */ 1596 1597 rpip = hba->sli.sli4.RPIp; 1598 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { 1599 if (rpip->state == RPI_STATE_FREE) { 1600 continue; 1601 } 1602 1603 (void) emlxs_rpi_free(port, rpip); 1604 } 1605 1606 kmem_free(hba->sli.sli4.RPIp, 1607 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount)); 1608 1609 hba->sli.sli4.RPIp = NULL; 1610 hba->sli.sli4.RPICount = 0; 1611 1612 /* Free the mutex */ 1613 1614 mutex_exit(&EMLXS_FCF_LOCK); 1615 mutex_destroy(&EMLXS_FCF_LOCK); 1616 1617 return; 1618 1619 } /* emlxs_fcf_fini() */ 1620 1621 1622 extern void 1623 emlxs_fcf_init(emlxs_hba_t *hba) 1624 { 1625 emlxs_port_t *port = &PPORT; 1626 emlxs_port_t *vport; 1627 uint16_t i; 1628 FCFIobj_t *fcfp; 1629 VFIobj_t *vfip; 1630 RPIobj_t *rpip; 1631 char buf[64]; 1632 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 1633 uint16_t index; 1634 1635 if (fcftab->table) { 1636 return; 1637 } 1638 1639 /* FCFTAB */ 1640 1641 bzero(fcftab, sizeof (FCFTable_t)); 1642 1643 (void) sprintf(buf, "%s_fcf_lock mutex", DRIVER_NAME); 1644 mutex_init(&EMLXS_FCF_LOCK, buf, MUTEX_DRIVER, NULL); 1645 mutex_enter(&EMLXS_FCF_LOCK); 1646 1647 fcftab->state = FCFTAB_STATE_OFFLINE; 1648 1649 /* FCFI */ 1650 1651 fcftab->table_count = hba->sli.sli4.FCFICount; 1652 fcftab->table = (FCFIobj_t *)kmem_zalloc( 1653 (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP); 1654 1655 fcfp = fcftab->table; 1656 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 1657 fcfp->index = i; 1658 fcfp->FCFI = 0xFFFF; 1659 fcfp->state = FCFI_STATE_FREE; 1660 } 1661 1662 /* VFI */ 1663 1664 hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc( 1665 (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP); 1666 1667 vfip = hba->sli.sli4.VFI_table; 1668 index = hba->sli.sli4.VFIBase; 1669 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++, index++) { 1670 vfip->VFI = index; 1671 vfip->index = i; 1672 vfip->state = VPI_STATE_OFFLINE; 1673 } 1674 1675 /* VPI */ 1676 1677 for (i = 0; i < MAX_VPORTS; i++) { 1678 vport = &VPORT(i); 1679 bzero(&vport->VPIobj, sizeof (VPIobj_t)); 1680 1681 vport->VPIobj.index = i; 1682 vport->VPIobj.VPI = i + hba->sli.sli4.VPIBase; 1683 vport->VPIobj.port = vport; 1684 vport->VPIobj.state = VPI_STATE_OFFLINE; 1685 1686 /* Init the Fabric RPI's */ 1687 rpip = &vport->VPIobj.fcf_rpi; 1688 rpip->state = RPI_STATE_FREE; 1689 rpip->RPI = 0xffff; 1690 rpip->index = 0xffff; 1691 rpip->did = FABRIC_DID; 1692 rpip->vpip = &vport->VPIobj; 1693 vport->VPIobj.rpip = rpip; 1694 } 1695 1696 /* RPI */ 1697 1698 hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc( 1699 (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP); 1700 1701 rpip = hba->sli.sli4.RPIp; 1702 index = hba->sli.sli4.RPIBase; 1703 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++, index++) { 1704 rpip->state = RPI_STATE_FREE; 1705 rpip->RPI = index; 1706 rpip->index = i; 1707 } 1708 1709 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 1710 "emlxs_fcf_init: %s flag=%x fcfi=%d vfi=%d vpi=%d rpi=%d", 1711 emlxs_fcftab_state_xlate(fcftab->state), 1712 fcftab->flag, 1713 fcftab->table_count, 1714 hba->sli.sli4.VFICount, 1715 MAX_VPORTS, 1716 hba->sli.sli4.RPICount); 1717 1718 mutex_exit(&EMLXS_FCF_LOCK); 1719 1720 return; 1721 1722 } /* emlxs_fcf_init() */ 1723 1724 1725 static char * 1726 emlxs_fcf_event_xlate(uint32_t state) 1727 { 1728 static char buffer[32]; 1729 uint32_t i; 1730 uint32_t count; 1731 1732 count = sizeof (emlxs_fcf_event_table) / sizeof (emlxs_table_t); 1733 for (i = 0; i < count; i++) { 1734 if (state == emlxs_fcf_event_table[i].code) { 1735 return (emlxs_fcf_event_table[i].string); 1736 } 1737 } 1738 1739 (void) sprintf(buffer, "event=0x%x", state); 1740 return (buffer); 1741 1742 } /* emlxs_fcf_event_xlate() */ 1743 1744 1745 static char * 1746 emlxs_fcf_reason_xlate(uint32_t reason) 1747 { 1748 static char buffer[32]; 1749 uint32_t i; 1750 uint32_t count; 1751 1752 count = sizeof (emlxs_fcf_reason_table) / sizeof (emlxs_table_t); 1753 for (i = 0; i < count; i++) { 1754 if (reason == emlxs_fcf_reason_table[i].code) { 1755 return (emlxs_fcf_reason_table[i].string); 1756 } 1757 } 1758 1759 (void) sprintf(buffer, "reason=0x%x", reason); 1760 return (buffer); 1761 1762 } /* emlxs_fcf_reason_xlate() */ 1763 1764 1765 extern void 1766 emlxs_fcf_timer_notify(emlxs_hba_t *hba) 1767 { 1768 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 1769 1770 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1771 return; 1772 } 1773 1774 if (fcftab->table == 0) { 1775 return; 1776 } 1777 1778 mutex_enter(&EMLXS_FCF_LOCK); 1779 1780 emlxs_fcftab_sol_timer(hba); 1781 1782 emlxs_fcftab_read_timer(hba); 1783 1784 emlxs_fcftab_offline_timer(hba); 1785 1786 mutex_exit(&EMLXS_FCF_LOCK); 1787 1788 return; 1789 1790 } /* emlxs_fcf_timer_notify() */ 1791 1792 1793 extern uint32_t 1794 emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait) 1795 { 1796 emlxs_hba_t *hba = HBA; 1797 emlxs_port_t *pport = &PPORT; 1798 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 1799 uint32_t rval; 1800 uint32_t i; 1801 1802 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1803 return (1); 1804 } 1805 1806 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1807 return (1); 1808 } 1809 1810 mutex_enter(&EMLXS_FCF_LOCK); 1811 1812 rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0); 1813 1814 if (wait && (rval == 0)) { 1815 /* Wait for FCF table to shutdown */ 1816 i = 0; 1817 while (i++ < 120) { 1818 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) { 1819 break; 1820 } 1821 1822 mutex_exit(&EMLXS_FCF_LOCK); 1823 DELAYMS(1000); 1824 mutex_enter(&EMLXS_FCF_LOCK); 1825 } 1826 1827 if (i >= 120) { 1828 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 1829 "fcf_shutdown_notify: %s flag=%x fcfi_online=%d. " 1830 "Shutdown timeout.", 1831 emlxs_fcftab_state_xlate(fcftab->state), 1832 fcftab->flag, fcftab->fcfi_online); 1833 } 1834 } 1835 1836 mutex_exit(&EMLXS_FCF_LOCK); 1837 1838 return (rval); 1839 1840 } /* emlxs_fcf_shutdown_notify() */ 1841 1842 1843 extern uint32_t 1844 emlxs_fcf_linkup_notify(emlxs_port_t *port) 1845 { 1846 emlxs_hba_t *hba = HBA; 1847 emlxs_port_t *pport = &PPORT; 1848 uint32_t rval; 1849 1850 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1851 return (1); 1852 } 1853 1854 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1855 return (1); 1856 } 1857 1858 mutex_enter(&EMLXS_FCF_LOCK); 1859 1860 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0); 1861 1862 mutex_exit(&EMLXS_FCF_LOCK); 1863 1864 return (rval); 1865 1866 } /* emlxs_fcf_linkup_notify() */ 1867 1868 1869 extern uint32_t 1870 emlxs_fcf_linkdown_notify(emlxs_port_t *port) 1871 { 1872 emlxs_hba_t *hba = HBA; 1873 emlxs_port_t *pport = &PPORT; 1874 uint32_t rval; 1875 1876 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1877 return (1); 1878 } 1879 1880 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1881 return (1); 1882 } 1883 1884 mutex_enter(&EMLXS_FCF_LOCK); 1885 1886 rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0); 1887 1888 mutex_exit(&EMLXS_FCF_LOCK); 1889 1890 return (rval); 1891 1892 } /* emlxs_fcf_linkdown_notify() */ 1893 1894 1895 extern uint32_t 1896 emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi) 1897 { 1898 emlxs_hba_t *hba = HBA; 1899 emlxs_port_t *pport = &PPORT; 1900 uint32_t rval; 1901 1902 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1903 return (1); 1904 } 1905 1906 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1907 return (1); 1908 } 1909 1910 mutex_enter(&EMLXS_FCF_LOCK); 1911 1912 rval = emlxs_fcftab_event(port, FCF_EVENT_CVL, 1913 (void *)((uintptr_t)vpi)); 1914 1915 mutex_exit(&EMLXS_FCF_LOCK); 1916 1917 return (rval); 1918 1919 } /* emlxs_fcf_cvl_notify() */ 1920 1921 1922 extern uint32_t 1923 emlxs_fcf_full_notify(emlxs_port_t *port) 1924 { 1925 emlxs_hba_t *hba = HBA; 1926 emlxs_port_t *pport = &PPORT; 1927 uint32_t rval; 1928 1929 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1930 return (1); 1931 } 1932 1933 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1934 return (1); 1935 } 1936 1937 mutex_enter(&EMLXS_FCF_LOCK); 1938 1939 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0); 1940 1941 mutex_exit(&EMLXS_FCF_LOCK); 1942 1943 return (rval); 1944 1945 } /* emlxs_fcf_full_notify() */ 1946 1947 1948 extern uint32_t 1949 emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index) 1950 { 1951 emlxs_hba_t *hba = HBA; 1952 emlxs_port_t *pport = &PPORT; 1953 uint32_t rval; 1954 1955 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1956 return (1); 1957 } 1958 1959 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1960 return (1); 1961 } 1962 1963 mutex_enter(&EMLXS_FCF_LOCK); 1964 1965 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND, 1966 (void *)((uintptr_t)fcf_index)); 1967 1968 mutex_exit(&EMLXS_FCF_LOCK); 1969 1970 return (rval); 1971 1972 } /* emlxs_fcf_found_notify() */ 1973 1974 1975 extern uint32_t 1976 emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index) 1977 { 1978 emlxs_hba_t *hba = HBA; 1979 emlxs_port_t *pport = &PPORT; 1980 uint32_t rval; 1981 1982 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 1983 return (1); 1984 } 1985 1986 if (!(pport->flag & EMLXS_PORT_BOUND)) { 1987 return (1); 1988 } 1989 1990 mutex_enter(&EMLXS_FCF_LOCK); 1991 1992 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED, 1993 (void *)((uintptr_t)fcf_index)); 1994 1995 mutex_exit(&EMLXS_FCF_LOCK); 1996 1997 return (rval); 1998 1999 } /* emlxs_fcf_changed_notify() */ 2000 2001 2002 extern uint32_t 2003 emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index) 2004 { 2005 emlxs_hba_t *hba = HBA; 2006 emlxs_port_t *pport = &PPORT; 2007 uint32_t rval; 2008 2009 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 2010 return (1); 2011 } 2012 2013 if (!(pport->flag & EMLXS_PORT_BOUND)) { 2014 return (1); 2015 } 2016 2017 mutex_enter(&EMLXS_FCF_LOCK); 2018 2019 rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST, 2020 (void *)((uintptr_t)fcf_index)); 2021 2022 mutex_exit(&EMLXS_FCF_LOCK); 2023 2024 return (rval); 2025 2026 } /* emlxs_fcf_lost_notify() */ 2027 2028 2029 2030 /* ************************************************************************** */ 2031 /* FCFTAB */ 2032 /* ************************************************************************** */ 2033 2034 static char * 2035 emlxs_fcftab_state_xlate(uint32_t state) 2036 { 2037 static char buffer[32]; 2038 uint32_t i; 2039 uint32_t count; 2040 2041 count = sizeof (emlxs_fcftab_state_table) / sizeof (emlxs_table_t); 2042 for (i = 0; i < count; i++) { 2043 if (state == emlxs_fcftab_state_table[i].code) { 2044 return (emlxs_fcftab_state_table[i].string); 2045 } 2046 } 2047 2048 (void) sprintf(buffer, "state=0x%x", state); 2049 return (buffer); 2050 2051 } /* emlxs_fcftab_state_xlate() */ 2052 2053 2054 static uint32_t 2055 emlxs_fcftab_action(emlxs_port_t *port, uint32_t evt, 2056 void *arg1) 2057 { 2058 emlxs_hba_t *hba = HBA; 2059 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2060 uint32_t rval; 2061 uint32_t(*func) (emlxs_port_t *, uint32_t, void *); 2062 uint32_t index; 2063 uint32_t events; 2064 uint16_t state; 2065 2066 /* Convert event to action table index */ 2067 switch (evt) { 2068 case FCF_EVENT_STATE_ENTER: 2069 index = 0; 2070 break; 2071 case FCF_EVENT_SHUTDOWN: 2072 index = 1; 2073 break; 2074 case FCF_EVENT_LINKUP: 2075 index = 2; 2076 break; 2077 case FCF_EVENT_LINKDOWN: 2078 index = 3; 2079 break; 2080 case FCF_EVENT_CVL: 2081 index = 4; 2082 break; 2083 case FCF_EVENT_FCF_FOUND: 2084 index = 5; 2085 break; 2086 case FCF_EVENT_FCF_LOST: 2087 index = 6; 2088 break; 2089 case FCF_EVENT_FCF_CHANGED: 2090 index = 7; 2091 break; 2092 case FCF_EVENT_FCFTAB_FULL: 2093 index = 8; 2094 break; 2095 case FCF_EVENT_FCFI_ONLINE: 2096 index = 9; 2097 break; 2098 case FCF_EVENT_FCFI_OFFLINE: 2099 index = 10; 2100 break; 2101 default: 2102 return (1); 2103 } 2104 2105 events = FCFTAB_ACTION_EVENTS; 2106 state = fcftab->state; 2107 2108 index += (state * events); 2109 func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *)) 2110 emlxs_fcftab_action_table[index]; 2111 2112 if (!func) { 2113 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 2114 "fcftab: %s:%s arg=%p. No action. Terminated.", 2115 emlxs_fcftab_state_xlate(fcftab->state), 2116 emlxs_fcf_event_xlate(evt), arg1); 2117 2118 return (1); 2119 } 2120 2121 rval = (func)(port, evt, arg1); 2122 2123 return (rval); 2124 2125 } /* emlxs_fcftab_action() */ 2126 2127 2128 static uint32_t 2129 emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt, 2130 void *arg1) 2131 { 2132 emlxs_hba_t *hba = HBA; 2133 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2134 uint32_t rval; 2135 2136 /* Filter events */ 2137 switch (evt) { 2138 case FCF_EVENT_SHUTDOWN: 2139 case FCF_EVENT_LINKUP: 2140 case FCF_EVENT_LINKDOWN: 2141 case FCF_EVENT_CVL: 2142 case FCF_EVENT_FCF_FOUND: 2143 case FCF_EVENT_FCF_LOST: 2144 case FCF_EVENT_FCF_CHANGED: 2145 case FCF_EVENT_FCFTAB_FULL: 2146 case FCF_EVENT_FCFI_OFFLINE: 2147 case FCF_EVENT_FCFI_ONLINE: 2148 break; 2149 2150 default: 2151 return (1); 2152 } 2153 2154 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 2155 "fcftab: %s:%s arg=%p.", 2156 emlxs_fcftab_state_xlate(fcftab->state), 2157 emlxs_fcf_event_xlate(evt), arg1); 2158 2159 rval = emlxs_fcftab_action(port, evt, arg1); 2160 2161 return (rval); 2162 2163 } /* emlxs_fcftab_event() */ 2164 2165 2166 /* EMLXS_FCF_LOCK must be held to enter */ 2167 /*ARGSUSED*/ 2168 static uint32_t 2169 emlxs_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason, 2170 uint32_t explain, void *arg1) 2171 { 2172 emlxs_hba_t *hba = HBA; 2173 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2174 uint32_t rval = 0; 2175 2176 if (state >= FCFTAB_ACTION_STATES) { 2177 return (1); 2178 } 2179 2180 if ((fcftab->state == state) && 2181 (reason != FCF_REASON_REENTER)) { 2182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2183 "fcftab_state: %s:%s:0x%x arg=%p. " 2184 "State not changed. Terminated.", 2185 emlxs_fcftab_state_xlate(state), 2186 emlxs_fcf_reason_xlate(reason), 2187 explain, arg1); 2188 2189 return (1); 2190 } 2191 2192 if (!reason) { 2193 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 2194 "fcftab:%s-->%s arg=%p", 2195 emlxs_fcftab_state_xlate(fcftab->state), 2196 emlxs_fcftab_state_xlate(state), arg1); 2197 } else if (reason == FCF_REASON_EVENT) { 2198 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 2199 "fcftab:%s-->%s:%s:%s arg=%p", 2200 emlxs_fcftab_state_xlate(fcftab->state), 2201 emlxs_fcftab_state_xlate(state), 2202 emlxs_fcf_reason_xlate(reason), 2203 emlxs_fcf_event_xlate(explain), arg1); 2204 } else if (explain) { 2205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 2206 "fcftab:%s-->%s:%s:0x%x arg=%p", 2207 emlxs_fcftab_state_xlate(fcftab->state), 2208 emlxs_fcftab_state_xlate(state), 2209 emlxs_fcf_reason_xlate(reason), 2210 explain, arg1); 2211 } else { 2212 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 2213 "fcftab:%s-->%s:%s arg=%p", 2214 emlxs_fcftab_state_xlate(fcftab->state), 2215 emlxs_fcftab_state_xlate(state), 2216 emlxs_fcf_reason_xlate(reason), arg1); 2217 } 2218 2219 fcftab->prev_state = fcftab->state; 2220 fcftab->prev_reason = fcftab->reason; 2221 fcftab->state = state; 2222 fcftab->reason = reason; 2223 2224 rval = emlxs_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1); 2225 2226 return (rval); 2227 2228 } /* emlxs_fcftab_state() */ 2229 2230 2231 /*ARGSUSED*/ 2232 static uint32_t 2233 emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt, 2234 void *arg1) 2235 { 2236 emlxs_hba_t *hba = HBA; 2237 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2238 uint32_t rval = 0; 2239 FCFIobj_t *fcfp; 2240 2241 if (evt != FCF_EVENT_FCFI_OFFLINE) { 2242 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2243 "fcftab_fcfi_offline_evt_action: %s:%s arg=%p flag=%x. " 2244 "Invalid event type. Terminated.", 2245 emlxs_fcftab_state_xlate(fcftab->state), 2246 emlxs_fcf_event_xlate(evt), arg1, 2247 fcftab->flag); 2248 return (1); 2249 } 2250 2251 fcfp = (FCFIobj_t *)arg1; 2252 2253 switch (fcftab->state) { 2254 case FCFTAB_STATE_SHUTDOWN: 2255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2256 "fcftab_fcfi_offline_evt_action:%d. Shutting down.", 2257 fcfp->fcf_index); 2258 2259 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN, 2260 FCF_REASON_REENTER, evt, arg1); 2261 break; 2262 2263 case FCFTAB_STATE_FCFI_OFFLINE: 2264 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2265 "fcftab_fcfi_offline_evt_action:%d. Offlining.", 2266 fcfp->fcf_index); 2267 2268 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE, 2269 FCF_REASON_REENTER, evt, arg1); 2270 break; 2271 2272 case FCFTAB_STATE_FCFI_ONLINE: 2273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2274 "fcftab_fcfi_offline_evt_action:%d. Attempting failover.", 2275 fcfp->fcf_index); 2276 2277 fcfp->flag |= EMLXS_FCFI_FAILED; 2278 2279 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, 2280 FCF_REASON_REENTER, evt, arg1); 2281 break; 2282 2283 case FCFTAB_STATE_ONLINE: 2284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2285 "fcftab_fcfi_offline_evt_action:%d.", 2286 fcfp->fcf_index); 2287 2288 rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE, 2289 FCF_REASON_REENTER, evt, arg1); 2290 break; 2291 2292 default: 2293 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2294 "fcftab_fcfi_offline_evt_action:%d %s. Terminated.", 2295 fcfp->fcf_index, 2296 emlxs_fcftab_state_xlate(fcftab->state)); 2297 break; 2298 } 2299 2300 return (rval); 2301 2302 } /* emlxs_fcftab_fcfi_offline_evt_action() */ 2303 2304 2305 /*ARGSUSED*/ 2306 static uint32_t 2307 emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt, 2308 void *arg1) 2309 { 2310 emlxs_hba_t *hba = HBA; 2311 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2312 uint32_t rval = 0; 2313 FCFIobj_t *fcfp; 2314 2315 if (evt != FCF_EVENT_FCFI_ONLINE) { 2316 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2317 "fcftab_fcfi_online_evt_action: %s:%s arg=%p flag=%x. " 2318 "Invalid event type. Terminated.", 2319 emlxs_fcftab_state_xlate(fcftab->state), 2320 emlxs_fcf_event_xlate(evt), arg1, 2321 fcftab->flag); 2322 return (1); 2323 } 2324 2325 fcfp = (FCFIobj_t *)arg1; 2326 2327 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2328 "fcftab_fcfi_online_evt_action:%d. Terminated.", 2329 fcfp->fcf_index); 2330 2331 return (rval); 2332 2333 } /* emlxs_fcftab_fcfi_online_evt_action() */ 2334 2335 2336 /*ARGSUSED*/ 2337 static uint32_t 2338 emlxs_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt, 2339 void *arg1) 2340 { 2341 emlxs_hba_t *hba = HBA; 2342 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2343 uint32_t rval; 2344 emlxs_port_t *vport; 2345 uint32_t vpi; 2346 VPIobj_t *vpip; 2347 2348 if (evt != FCF_EVENT_CVL) { 2349 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2350 "fcftab_cvl_evt_action: %s:%s arg=%p flag=%x. " 2351 "Invalid event type. Terminated.", 2352 emlxs_fcftab_state_xlate(fcftab->state), 2353 emlxs_fcf_event_xlate(evt), arg1, 2354 fcftab->flag); 2355 return (1); 2356 } 2357 2358 /* Pause VPI */ 2359 vpi = (uint32_t)((uintptr_t)arg1); 2360 vport = &VPORT(vpi); 2361 vpip = &vport->VPIobj; 2362 2363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2364 "fcftab_cvl_evt_action: %s gen=%x. Pausing VPI:%d.", 2365 emlxs_fcftab_state_xlate(fcftab->state), 2366 fcftab->generation, 2367 vpip->VPI); 2368 2369 rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip); 2370 2371 switch (fcftab->state) { 2372 case FCFTAB_STATE_SOLICIT: 2373 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2374 "fcftab_cvl_evt_action: %s gen=%x. " 2375 "Already soliciting. Terminated.", 2376 emlxs_fcftab_state_xlate(fcftab->state), 2377 fcftab->generation); 2378 break; 2379 2380 default: 2381 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 2382 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 2383 fcftab->generation++; 2384 2385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2386 "fcftab_cvl_evt_action: %s gen=%x. Soliciting.", 2387 emlxs_fcftab_state_xlate(fcftab->state), 2388 fcftab->generation); 2389 2390 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 2391 FCF_REASON_EVENT, evt, arg1); 2392 break; 2393 } 2394 2395 return (rval); 2396 2397 } /* emlxs_fcftab_cvl_evt_action() */ 2398 2399 2400 /*ARGSUSED*/ 2401 static uint32_t 2402 emlxs_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt, 2403 void *arg1) 2404 { 2405 emlxs_hba_t *hba = HBA; 2406 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2407 uint32_t rval = 0; 2408 emlxs_config_t *cfg = &CFG; 2409 2410 if (evt != FCF_EVENT_LINKUP) { 2411 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2412 "fcftab_linkup_evt_action: %s:%s arg=%p flag=%x. " 2413 "Invalid event type. Terminated.", 2414 emlxs_fcftab_state_xlate(fcftab->state), 2415 emlxs_fcf_event_xlate(evt), arg1, 2416 fcftab->flag); 2417 return (1); 2418 } 2419 2420 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2421 "fcftab_linkup_evt_action: %s:%s arg=%p gen=%x. Link up.", 2422 emlxs_fcftab_state_xlate(fcftab->state), 2423 emlxs_fcf_event_xlate(evt), arg1, 2424 fcftab->generation); 2425 2426 mutex_enter(&EMLXS_PORT_LOCK); 2427 if (hba->state < FC_LINK_UP) { 2428 HBASTATS.LinkUp++; 2429 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 2430 } 2431 hba->discovery_timer = 2432 hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 2433 cfg[CFG_DISC_TIMEOUT].current; 2434 mutex_exit(&EMLXS_PORT_LOCK); 2435 2436 emlxs_log_link_event(port); 2437 2438 switch (fcftab->state) { 2439 case FCFTAB_STATE_SOLICIT: 2440 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2441 "fcftab_linkup_evt_action: %s gen=%x. " 2442 "Already soliciting. Terminated.", 2443 emlxs_fcftab_state_xlate(fcftab->state), 2444 fcftab->generation); 2445 break; 2446 2447 default: 2448 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 2449 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 2450 fcftab->generation++; 2451 2452 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2453 "fcftab_linkup_evt_action: %s gen=%x. Soliciting.", 2454 emlxs_fcftab_state_xlate(fcftab->state), 2455 fcftab->generation); 2456 2457 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 2458 FCF_REASON_EVENT, evt, arg1); 2459 break; 2460 } 2461 2462 return (rval); 2463 2464 } /* emlxs_fcftab_linkup_evt_action() */ 2465 2466 2467 /*ARGSUSED*/ 2468 static uint32_t 2469 emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt, 2470 void *arg1) 2471 { 2472 emlxs_hba_t *hba = HBA; 2473 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2474 uint32_t rval = 0; 2475 int32_t i; 2476 FCFIobj_t *fcfp; 2477 2478 if (evt != FCF_EVENT_LINKDOWN) { 2479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2480 "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. " 2481 "Invalid event type. Terminated.", 2482 emlxs_fcftab_state_xlate(fcftab->state), 2483 emlxs_fcf_event_xlate(evt), arg1, 2484 fcftab->flag); 2485 return (1); 2486 } 2487 2488 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 2489 fcftab->flag |= EMLXS_FCFTAB_OFFLINE_REQ; 2490 2491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2492 "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. Linkdown.", 2493 emlxs_fcftab_state_xlate(fcftab->state), 2494 emlxs_fcf_event_xlate(evt), arg1, 2495 fcftab->flag); 2496 2497 mutex_enter(&EMLXS_PORT_LOCK); 2498 if (hba->state > FC_LINK_DOWN) { 2499 HBASTATS.LinkDown++; 2500 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 2501 } 2502 hba->flag &= FC_LINKDOWN_MASK; 2503 hba->discovery_timer = 0; 2504 mutex_exit(&EMLXS_PORT_LOCK); 2505 2506 emlxs_log_link_event(port); 2507 2508 /* Pause all active FCFI's */ 2509 for (i = 0; i < fcftab->fcfi_count; i++) { 2510 fcfp = fcftab->fcfi[i]; 2511 2512 if ((fcfp->state == FCFI_STATE_OFFLINE) || 2513 (fcfp->state == FCFI_STATE_PAUSED)) { 2514 break; 2515 } 2516 2517 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2518 "fcftab_linkdown_evt_action: Pausing FCFI:%d.", 2519 fcfp->fcf_index); 2520 2521 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp); 2522 } 2523 2524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2525 "fcftab_linkdown_evt_action: Going offline."); 2526 2527 switch (fcftab->state) { 2528 case FCFTAB_STATE_OFFLINE: 2529 rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, 2530 FCF_REASON_REENTER, evt, arg1); 2531 break; 2532 2533 default: 2534 rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, 2535 FCF_REASON_EVENT, evt, arg1); 2536 break; 2537 } 2538 2539 return (rval); 2540 2541 } /* emlxs_fcftab_linkdown_evt_action() */ 2542 2543 2544 /*ARGSUSED*/ 2545 static uint32_t 2546 emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt, 2547 void *arg1) 2548 { 2549 emlxs_hba_t *hba = HBA; 2550 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2551 uint32_t rval = 0; 2552 2553 if (evt != FCF_EVENT_SHUTDOWN) { 2554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2555 "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " 2556 "Invalid event type. Terminated.", 2557 emlxs_fcftab_state_xlate(fcftab->state), 2558 emlxs_fcf_event_xlate(evt), arg1, 2559 fcftab->flag); 2560 return (1); 2561 } 2562 2563 if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) { 2564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2565 "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " 2566 "Already shut down. Terminated.", 2567 emlxs_fcftab_state_xlate(fcftab->state), 2568 emlxs_fcf_event_xlate(evt), arg1, 2569 fcftab->flag); 2570 return (1); 2571 } 2572 2573 if (fcftab->state == FCFTAB_STATE_SHUTDOWN) { 2574 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2575 "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " 2576 "Already shutting down. Terminated.", 2577 emlxs_fcftab_state_xlate(fcftab->state), 2578 emlxs_fcf_event_xlate(evt), arg1, 2579 fcftab->flag); 2580 return (1); 2581 } 2582 2583 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2584 "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " 2585 "Shutting down.", 2586 emlxs_fcftab_state_xlate(fcftab->state), 2587 emlxs_fcf_event_xlate(evt), arg1, 2588 fcftab->flag); 2589 2590 if (hba->state > FC_LINK_DOWN) { 2591 mutex_enter(&EMLXS_PORT_LOCK); 2592 if (hba->state > FC_LINK_DOWN) { 2593 HBASTATS.LinkDown++; 2594 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 2595 } 2596 hba->flag &= FC_LINKDOWN_MASK; 2597 hba->discovery_timer = 0; 2598 mutex_exit(&EMLXS_PORT_LOCK); 2599 2600 emlxs_log_link_event(port); 2601 } 2602 2603 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN, 2604 FCF_REASON_EVENT, evt, arg1); 2605 2606 return (rval); 2607 2608 } /* emlxs_fcftab_shutdown_evt_action() */ 2609 2610 2611 static uint32_t 2612 emlxs_fcftab_req_handler(emlxs_port_t *port, void *arg1) 2613 { 2614 emlxs_hba_t *hba = HBA; 2615 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2616 uint32_t rval = 0; 2617 2618 if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) { 2619 return (1); 2620 } 2621 2622 if (fcftab->flag & EMLXS_FCFTAB_OFFLINE_REQ) { 2623 rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, 2624 FCF_REASON_REQUESTED, 0, arg1); 2625 } 2626 2627 else if (fcftab->flag & EMLXS_FCFTAB_SOL_REQ) { 2628 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 2629 FCF_REASON_REQUESTED, 0, arg1); 2630 } 2631 2632 else if (fcftab->flag & EMLXS_FCFTAB_READ_REQ) { 2633 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, 2634 FCF_REASON_REQUESTED, 0, FCFTAB_READ_ALL); 2635 } 2636 2637 return (rval); 2638 2639 } /* emlxs_fcftab_req_handler() */ 2640 2641 2642 static void 2643 emlxs_fcftab_read_timer(emlxs_hba_t *hba) 2644 { 2645 emlxs_port_t *port = &PPORT; 2646 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2647 2648 /* Check FCF timer */ 2649 if (!fcftab->read_timer || 2650 (hba->timer_tics <= fcftab->read_timer)) { 2651 return; 2652 } 2653 fcftab->read_timer = 0; 2654 fcftab->flag |= EMLXS_FCFTAB_READ_REQ; 2655 2656 switch (fcftab->state) { 2657 case FCFTAB_STATE_SOLICIT_CMPL: 2658 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2659 "fcftab_timer: %s", 2660 emlxs_fcftab_state_xlate(fcftab->state)); 2661 2662 (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ, 0, 0, 2663 FCFTAB_READ_ALL); 2664 break; 2665 2666 default: 2667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2668 "fcftab_timer: %s Terminated.", 2669 emlxs_fcftab_state_xlate(fcftab->state)); 2670 break; 2671 } 2672 2673 return; 2674 2675 } /* emlxs_fcftab_read_timer() */ 2676 2677 2678 static void 2679 emlxs_fcftab_sol_timer(emlxs_hba_t *hba) 2680 { 2681 emlxs_port_t *port = &PPORT; 2682 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2683 2684 /* Check FCF timer */ 2685 if (!fcftab->sol_timer || 2686 (hba->timer_tics <= fcftab->sol_timer)) { 2687 return; 2688 } 2689 fcftab->sol_timer = 0; 2690 2691 switch (fcftab->state) { 2692 case FCFTAB_STATE_ONLINE: 2693 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 2694 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 2695 fcftab->generation++; 2696 2697 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2698 "fcftab_sol_timer: %s gen=%x. Soliciting.", 2699 emlxs_fcftab_state_xlate(fcftab->state), 2700 fcftab->generation); 2701 2702 (void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 2703 FCF_REASON_EVENT, 0, 0); 2704 break; 2705 2706 default: 2707 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2708 "fcftab_sol_timer: %s Terminated.", 2709 emlxs_fcftab_state_xlate(fcftab->state)); 2710 break; 2711 } 2712 2713 return; 2714 2715 } /* emlxs_fcftab_sol_timer() */ 2716 2717 2718 static void 2719 emlxs_fcftab_offline_timer(emlxs_hba_t *hba) 2720 { 2721 emlxs_port_t *port = &PPORT; 2722 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2723 uint32_t i; 2724 FCFIobj_t *fcfp; 2725 2726 for (i = 0; i < fcftab->fcfi_count; i++) { 2727 fcfp = fcftab->fcfi[i]; 2728 2729 /* Check offline timer */ 2730 if (!fcfp->offline_timer || 2731 (hba->timer_tics <= fcfp->offline_timer)) { 2732 continue; 2733 } 2734 fcfp->offline_timer = 0; 2735 2736 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2737 "fcftab_offline_timer:%d %s. Offlining.", 2738 fcfp->fcf_index, 2739 emlxs_fcfi_state_xlate(fcfp->state)); 2740 2741 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp); 2742 } 2743 2744 return; 2745 2746 } /* emlxs_fcftab_offline_timer() */ 2747 2748 2749 /*ARGSUSED*/ 2750 static uint32_t 2751 emlxs_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt, 2752 void *arg1) 2753 { 2754 emlxs_hba_t *hba = HBA; 2755 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2756 uint32_t rval; 2757 2758 fcftab->attempts++; 2759 2760 if (fcftab->state != FCFTAB_STATE_SOLICIT_FAILED) { 2761 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2762 "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d. " 2763 "Invalid state. Terminated.", 2764 emlxs_fcftab_state_xlate(fcftab->state), 2765 emlxs_fcf_event_xlate(evt), 2766 arg1, fcftab->attempts); 2767 return (1); 2768 } 2769 2770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2771 "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d reason=%x", 2772 emlxs_fcftab_state_xlate(fcftab->state), 2773 emlxs_fcf_event_xlate(evt), arg1, 2774 fcftab->attempts, 2775 fcftab->reason); 2776 2777 if ((fcftab->reason == FCF_REASON_SEND_FAILED) || 2778 (fcftab->attempts >= 3)) { 2779 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL, 2780 FCF_REASON_OP_FAILED, 0, arg1); 2781 } else { 2782 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 2783 FCF_REASON_OP_FAILED, 0, arg1); 2784 } 2785 2786 return (rval); 2787 2788 } /* emlxs_fcftab_sol_failed_action() */ 2789 2790 2791 /*ARGSUSED*/ 2792 static uint32_t 2793 emlxs_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 2794 { 2795 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 2796 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2797 MAILBOX4 *mb4 = (MAILBOX4 *)mbq; 2798 uint32_t generation; 2799 mbox_rsp_hdr_t *hdr_rsp; 2800 MATCHMAP *mp; 2801 uint32_t status = MGMT_STATUS_FCF_IN_USE; 2802 uint32_t xstatus = 0; 2803 uint32_t fip_mode = 1; 2804 2805 mutex_enter(&EMLXS_FCF_LOCK); 2806 2807 if (mbq->nonembed) { 2808 fip_mode = 0; 2809 2810 mp = (MATCHMAP *)mbq->nonembed; 2811 mbq->nonembed = NULL; 2812 2813 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 2814 status = hdr_rsp->status; 2815 xstatus = hdr_rsp->extra_status; 2816 2817 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 2818 } 2819 2820 if (fcftab->state != FCFTAB_STATE_SOLICIT) { 2821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2822 "fcftab_sol_mbcmpl: %s. Terminated.", 2823 emlxs_fcftab_state_xlate(fcftab->state)); 2824 2825 mutex_exit(&EMLXS_FCF_LOCK); 2826 return (0); 2827 } 2828 2829 generation = (uint32_t)((uintptr_t)mbq->context); 2830 if (generation != fcftab->generation) { 2831 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2832 "fcftab_sol_mbcmpl: %s gen=%x,%x. " 2833 "Incorrect generation. Terminated.", 2834 emlxs_fcftab_state_xlate(fcftab->state), 2835 generation, fcftab->generation); 2836 2837 mutex_exit(&EMLXS_FCF_LOCK); 2838 return (0); 2839 } 2840 2841 if (mb4->mbxStatus) { 2842 if (fip_mode) { 2843 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2844 "fcftab_sol_mbcmpl:failed. status=%x", 2845 mb4->mbxStatus); 2846 2847 (void) emlxs_fcftab_state(port, 2848 FCFTAB_STATE_SOLICIT_FAILED, 2849 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 2850 2851 mutex_exit(&EMLXS_FCF_LOCK); 2852 return (0); 2853 2854 } else if ((status == 0)||(status != MGMT_STATUS_FCF_IN_USE)) { 2855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2856 "fcftab_sol_mbcmpl:failed. status=%x,%x,%x", 2857 mb4->mbxStatus, status, 2858 xstatus); 2859 2860 (void) emlxs_fcftab_state(port, 2861 FCFTAB_STATE_SOLICIT_FAILED, 2862 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 2863 2864 mutex_exit(&EMLXS_FCF_LOCK); 2865 return (0); 2866 } 2867 } 2868 2869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2870 "fcftab_sol_mbcmpl: %s gen=%x", 2871 emlxs_fcftab_state_xlate(fcftab->state), 2872 fcftab->generation); 2873 2874 (void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL, 2875 0, 0, 0); 2876 2877 mutex_exit(&EMLXS_FCF_LOCK); 2878 return (0); 2879 2880 } /* emlxs_fcftab_sol_mbcmpl() */ 2881 2882 2883 /*ARGSUSED*/ 2884 static uint32_t 2885 emlxs_fcftab_sol_action(emlxs_port_t *port, uint32_t evt, 2886 void *arg1) 2887 { 2888 emlxs_hba_t *hba = HBA; 2889 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 2890 MAILBOXQ *mbq; 2891 MAILBOX4 *mb4; 2892 MATCHMAP *mp = NULL; 2893 uint32_t rval; 2894 2895 if (fcftab->state != FCFTAB_STATE_SOLICIT) { 2896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 2897 "fcftab_sol_action: %s:%s arg=%p. " 2898 "Invalid state. Terminated.", 2899 emlxs_fcftab_state_xlate(fcftab->state), 2900 emlxs_fcf_event_xlate(evt), arg1); 2901 return (1); 2902 } 2903 2904 if ((fcftab->prev_state != FCFTAB_STATE_SOLICIT_FAILED) || 2905 (fcftab->flag & EMLXS_FCFTAB_SOL_REQ)) { 2906 fcftab->flag &= ~EMLXS_FCFTAB_SOL_REQ; 2907 fcftab->attempts = 0; 2908 } 2909 2910 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 2911 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2912 "fcftab_sol_action: %s:%s arg=%p gen=%d flag=%x. " 2913 "Handling request.", 2914 emlxs_fcftab_state_xlate(fcftab->state), 2915 emlxs_fcf_event_xlate(evt), arg1, 2916 fcftab->generation, 2917 fcftab->flag); 2918 2919 rval = emlxs_fcftab_req_handler(port, arg1); 2920 return (rval); 2921 } 2922 2923 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 2924 "fcftab_sol_action: %s:%s arg = %p gen=%x fip=%x. " 2925 "Requesting solicit.", 2926 emlxs_fcftab_state_xlate(fcftab->state), 2927 emlxs_fcf_event_xlate(evt), arg1, 2928 fcftab->generation, 2929 ((hba->flag & FC_FIP_SUPPORTED)? 1:0)); 2930 2931 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 2932 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED, 2933 FCF_REASON_NO_MBOX, 0, 0); 2934 return (rval); 2935 } 2936 2937 mb4 = (MAILBOX4*)mbq; 2938 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 2939 2940 if (hba->flag & FC_FIP_SUPPORTED) { 2941 IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf; 2942 2943 mbq->nonembed = NULL; 2944 mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl; 2945 mbq->context = (void *)((uintptr_t)fcftab->generation); 2946 mbq->port = (void *)port; 2947 2948 mb4->un.varSLIConfig.be.embedded = 1; 2949 mb4->mbxCommand = MBX_SLI_CONFIG; 2950 mb4->mbxOwner = OWN_HOST; 2951 mb4->un.varSLIConfig.be.payload_length = 2952 sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE) + 2953 IOCTL_HEADER_SZ; 2954 mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 2955 IOCTL_SUBSYSTEM_FCOE; 2956 mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = 2957 FCOE_OPCODE_REDISCOVER_FCF_TABLE; 2958 mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 2959 mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 2960 sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE); 2961 2962 fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *) 2963 &mb4->un.varSLIConfig.payload; 2964 fcf->params.request.fcf_count = 0; /* invalidate FCF table */ 2965 2966 } else { /* Non-FIP */ 2967 2968 /* Non-FIP uses a persistent FCF entry that */ 2969 /* we must add to the table */ 2970 2971 IOCTL_FCOE_ADD_FCF_TABLE *fcf; 2972 mbox_req_hdr_t *hdr_req; 2973 FCF_RECORD_t *fcf_rec; 2974 uint8_t bitmap[512]; 2975 uint16_t i; 2976 2977 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 2978 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 2979 2980 rval = emlxs_fcftab_state(port, 2981 FCFTAB_STATE_SOLICIT_FAILED, 2982 FCF_REASON_NO_BUFFER, 0, arg1); 2983 return (rval); 2984 } 2985 bzero(mp->virt, mp->size); 2986 2987 mbq->nonembed = (void *)mp; 2988 mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl; 2989 mbq->context = (void *)((uintptr_t)fcftab->generation); 2990 mbq->port = (void *)port; 2991 2992 mb4->un.varSLIConfig.be.embedded = 0; 2993 mb4->mbxCommand = MBX_SLI_CONFIG; 2994 mb4->mbxOwner = OWN_HOST; 2995 2996 hdr_req = (mbox_req_hdr_t *)mp->virt; 2997 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 2998 hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE; 2999 hdr_req->timeout = 0; 3000 hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE); 3001 3002 fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1); 3003 fcf->params.request.fcf_index = 0; 3004 3005 fcf_rec = &fcf->params.request.fcf_entry; 3006 fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ; 3007 fcf_rec->fka_adv_period = 0; 3008 fcf_rec->fip_priority = 128; 3009 3010 #ifdef EMLXS_BIG_ENDIAN 3011 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3; 3012 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2; 3013 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1; 3014 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0; 3015 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5; 3016 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4; 3017 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2]; 3018 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; 3019 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0]; 3020 #endif /* EMLXS_BIG_ENDIAN */ 3021 #ifdef EMLXS_LITTLE_ENDIAN 3022 fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0; 3023 fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1; 3024 fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2; 3025 fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3; 3026 fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4; 3027 fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5; 3028 fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0]; 3029 fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; 3030 fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2]; 3031 #endif /* EMLXS_LITTLE_ENDIAN */ 3032 3033 if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) { 3034 bzero((void *) bitmap, 512); 3035 i = hba->sli.sli4.cfgFCOE.VLanId; 3036 bitmap[i / 8] = (1 << (i % 8)); 3037 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512); 3038 } else { 3039 bzero((void *) bitmap, 512); 3040 bitmap[0] = 1; /* represents bit 0 */ 3041 BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512); 3042 } 3043 3044 fcf_rec->fcf_valid = 1; 3045 fcf_rec->fcf_available = 1; 3046 } 3047 3048 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3049 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3050 if (mp) { 3051 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 3052 } 3053 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 3054 3055 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED, 3056 FCF_REASON_SEND_FAILED, rval, 0); 3057 3058 return (rval); 3059 } 3060 3061 return (0); 3062 3063 3064 } /* emlxs_fcftab_sol_action() */ 3065 3066 3067 /*ARGSUSED*/ 3068 static uint32_t 3069 emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt, 3070 void *arg1) 3071 { 3072 emlxs_hba_t *hba = HBA; 3073 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3074 uint32_t rval; 3075 emlxs_config_t *cfg = &CFG; 3076 3077 if (fcftab->state != FCFTAB_STATE_SOLICIT_CMPL) { 3078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3079 "fcftab_sol_cmpl_action: %s:%s arg=%p " 3080 "Invalid state. Terminated.", 3081 emlxs_fcftab_state_xlate(fcftab->state), 3082 emlxs_fcf_event_xlate(evt), arg1); 3083 return (1); 3084 } 3085 3086 /* Increment the generation counter */ 3087 fcftab->generation++; 3088 3089 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 3090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3091 "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d flag=%x. " 3092 "Handling request.", 3093 emlxs_fcftab_state_xlate(fcftab->state), 3094 emlxs_fcf_event_xlate(evt), arg1, 3095 fcftab->generation, 3096 fcftab->flag); 3097 3098 rval = emlxs_fcftab_req_handler(port, arg1); 3099 return (rval); 3100 } 3101 3102 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3103 "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d. " 3104 "Starting timer (%d secs).", 3105 emlxs_fcftab_state_xlate(fcftab->state), 3106 emlxs_fcf_event_xlate(evt), arg1, 3107 fcftab->generation, 3108 cfg[CFG_FCF_SOLICIT_DELAY].current); 3109 3110 /* Start the read timer */ 3111 fcftab->read_timer = hba->timer_tics + 3112 cfg[CFG_FCF_SOLICIT_DELAY].current; 3113 3114 return (0); 3115 3116 } /* emlxs_fcftab_sol_cmpl_action() */ 3117 3118 3119 /*ARGSUSED*/ 3120 static uint32_t 3121 emlxs_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 3122 { 3123 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 3124 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3125 MAILBOX4 *mb4 = (MAILBOX4 *)mbq; 3126 mbox_rsp_hdr_t *hdr_rsp; 3127 IOCTL_FCOE_READ_FCF_TABLE *fcf; 3128 FCF_RECORD_t *fcfrec; 3129 FCFIobj_t *fcfp; 3130 MATCHMAP *mp; 3131 uint32_t index; 3132 uint32_t event_tag; 3133 3134 mutex_enter(&EMLXS_FCF_LOCK); 3135 3136 if (fcftab->state != FCFTAB_STATE_READ) { 3137 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3138 "fcftab_read_mbcmpl: state=%s. Terminated.", 3139 emlxs_fcftab_state_xlate(fcftab->state)); 3140 3141 mutex_exit(&EMLXS_FCF_LOCK); 3142 return (0); 3143 } 3144 3145 index = (uint32_t)((uintptr_t)mbq->context); 3146 mp = (MATCHMAP *)mbq->nonembed; 3147 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 3148 3149 if (mb4->mbxStatus || hdr_rsp->status) { 3150 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3151 "fcftab_read_mbcmpl:%d failed. status=%x,%x,%x", 3152 index, mb4->mbxStatus, hdr_rsp->status, 3153 hdr_rsp->extra_status); 3154 3155 (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, 3156 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 3157 3158 mutex_exit(&EMLXS_FCF_LOCK); 3159 return (0); 3160 } 3161 3162 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3163 "fcftab_read_mbcmpl: state=%s", 3164 emlxs_fcftab_state_xlate(fcftab->state)); 3165 3166 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1); 3167 fcfrec = &fcf->params.response.fcf_entry[0]; 3168 3169 #ifdef EMLXS_BIG_ENDIAN 3170 { 3171 uint32_t *iptr; 3172 uint32_t i; 3173 uint8_t j; 3174 uint16_t s; 3175 uint16_t *sptr; 3176 3177 /* Fix up data in FCF record */ 3178 SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8); 3179 SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8); 3180 SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512); 3181 3182 iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0]; 3183 i = *iptr; 3184 *iptr = SWAP32(i); 3185 3186 sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0]; 3187 s = *sptr; 3188 *sptr = SWAP16(s); 3189 3190 j = fcfrec->fc_map[0]; 3191 fcfrec->fc_map[0] = fcfrec->fc_map[2]; 3192 fcfrec->fc_map[2] = j; 3193 } 3194 #endif /* EMLXS_BIG_ENDIAN */ 3195 3196 event_tag = fcf->params.response.event_tag; 3197 3198 /* Try to find existing fcfrec */ 3199 fcfp = emlxs_fcfi_find(port, fcfrec, 0); 3200 3201 /* If not found, allocate a new one */ 3202 if (!fcfp) { 3203 fcfp = emlxs_fcfi_alloc(port); 3204 } 3205 3206 if (!fcfp) { 3207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3208 "fcftab_read_mbcmpl:%d failed. Unable to allocate fcfi.", 3209 index); 3210 3211 (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, 3212 FCF_REASON_NO_FCFI, 0, 0); 3213 3214 mutex_exit(&EMLXS_FCF_LOCK); 3215 return (0); 3216 } 3217 3218 /* Update the FCFI */ 3219 emlxs_fcfi_update(port, fcfp, fcfrec, event_tag); 3220 3221 /* Check if another record needs to be acquired */ 3222 if (fcf->params.response.next_valid_fcf_index != 0xffff) { 3223 fcftab->index = fcf->params.response.next_valid_fcf_index; 3224 3225 (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ, 3226 FCF_REASON_REENTER, 0, 3227 (void *)((uintptr_t)fcf->params.response. 3228 next_valid_fcf_index)); 3229 } else { 3230 (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL, 3231 0, 0, 0); 3232 } 3233 3234 mutex_exit(&EMLXS_FCF_LOCK); 3235 return (0); 3236 3237 } /* emlxs_fcftab_read_mbcmpl() */ 3238 3239 3240 /*ARGSUSED*/ 3241 static uint32_t 3242 emlxs_fcftab_read_action(emlxs_port_t *port, uint32_t evt, 3243 void *arg1) 3244 { 3245 emlxs_hba_t *hba = HBA; 3246 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3247 MAILBOXQ *mbq; 3248 MAILBOX4 *mb4; 3249 IOCTL_FCOE_READ_FCF_TABLE *fcf; 3250 uint32_t rval; 3251 MATCHMAP *mp; 3252 mbox_req_hdr_t *hdr_req; 3253 uint16_t index; 3254 3255 if (fcftab->state != FCFTAB_STATE_READ) { 3256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3257 "fcftab_read_action: %s:%s arg=%p. " 3258 "Invalid state. Terminated.", 3259 emlxs_fcftab_state_xlate(fcftab->state), 3260 emlxs_fcf_event_xlate(evt), arg1); 3261 return (1); 3262 } 3263 3264 fcftab->flag &= ~EMLXS_FCFTAB_READ_REQ; 3265 3266 if (fcftab->prev_state != FCFTAB_STATE_READ_FAILED) { 3267 fcftab->attempts = 0; 3268 } 3269 3270 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 3271 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3272 "fcftab_read_action: %s:%s arg=%p flag=%x. " 3273 "Handling request.", 3274 emlxs_fcftab_state_xlate(fcftab->state), 3275 emlxs_fcf_event_xlate(evt), arg1, 3276 fcftab->flag); 3277 3278 rval = emlxs_fcftab_req_handler(port, arg1); 3279 return (rval); 3280 } 3281 3282 index = (uint16_t)((uintptr_t)arg1); 3283 3284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3285 "fcftab_read_action: %s:%s arg=%p attempts=%d. Reading FCF.", 3286 emlxs_fcftab_state_xlate(fcftab->state), 3287 emlxs_fcf_event_xlate(evt), arg1, 3288 fcftab->attempts); 3289 3290 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 3291 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, 3292 FCF_REASON_NO_MBOX, 0, arg1); 3293 return (rval); 3294 } 3295 mb4 = (MAILBOX4*)mbq; 3296 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 3297 3298 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 3299 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 3300 3301 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, 3302 FCF_REASON_NO_BUFFER, 0, arg1); 3303 return (rval); 3304 } 3305 bzero(mp->virt, mp->size); 3306 3307 mbq->nonembed = (void *)mp; 3308 mbq->mbox_cmpl = emlxs_fcftab_read_mbcmpl; 3309 mbq->context = (void *)((uintptr_t)index); 3310 mbq->port = (void *)port; 3311 3312 mb4->un.varSLIConfig.be.embedded = 0; 3313 mb4->mbxCommand = MBX_SLI_CONFIG; 3314 mb4->mbxOwner = OWN_HOST; 3315 3316 hdr_req = (mbox_req_hdr_t *)mp->virt; 3317 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 3318 hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE; 3319 hdr_req->timeout = 0; 3320 hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE); 3321 3322 fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1); 3323 fcf->params.request.fcf_index = index; 3324 3325 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 3326 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 3327 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 3328 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 3329 3330 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, 3331 FCF_REASON_SEND_FAILED, rval, arg1); 3332 3333 return (rval); 3334 } 3335 3336 return (0); 3337 3338 } /* emlxs_fcftab_read_action() */ 3339 3340 3341 /*ARGSUSED*/ 3342 static uint32_t 3343 emlxs_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt, 3344 void *arg1) 3345 { 3346 emlxs_hba_t *hba = HBA; 3347 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3348 uint32_t rval; 3349 3350 fcftab->attempts++; 3351 3352 if (fcftab->state != FCFTAB_STATE_READ_FAILED) { 3353 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3354 "fcftab_read_failed_action: %s:%s arg=%p attempt=%d. " 3355 "Invalid state. Terminated.", 3356 emlxs_fcftab_state_xlate(fcftab->state), 3357 emlxs_fcf_event_xlate(evt), 3358 arg1, fcftab->attempts); 3359 3360 return (1); 3361 } 3362 3363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3364 "fcftab_read_failed_action: %s:%s arg=%p attempt=%d reason=%x", 3365 emlxs_fcftab_state_xlate(fcftab->state), 3366 emlxs_fcf_event_xlate(evt), arg1, 3367 fcftab->attempts, 3368 fcftab->reason); 3369 3370 if ((fcftab->reason == FCF_REASON_SEND_FAILED) || 3371 (fcftab->attempts >= 3)) { 3372 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL, 3373 FCF_REASON_OP_FAILED, fcftab->attempts, arg1); 3374 } else { 3375 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, 3376 FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL); 3377 } 3378 3379 return (rval); 3380 3381 } /* emlxs_fcftab_read_failed_action() */ 3382 3383 3384 /*ARGSUSED*/ 3385 static uint32_t 3386 emlxs_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt, 3387 void *arg1) 3388 { 3389 emlxs_hba_t *hba = HBA; 3390 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3391 uint32_t rval; 3392 FCFIobj_t *fcfp; 3393 uint32_t i; 3394 3395 if (fcftab->state != FCFTAB_STATE_READ_CMPL) { 3396 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3397 "fcftab_read_cmpl_action: %s:%s arg=%p. " 3398 "Invalid state. Terminated.", 3399 emlxs_fcftab_state_xlate(fcftab->state), 3400 emlxs_fcf_event_xlate(evt), arg1); 3401 return (1); 3402 } 3403 3404 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3405 "fcftab_read_cmpl_action: %s:%s arg=%p attempts=%d. " 3406 "Cleaning table.", 3407 emlxs_fcftab_state_xlate(fcftab->state), 3408 emlxs_fcf_event_xlate(evt), arg1, 3409 fcftab->attempts); 3410 3411 /* Clean FCFI table */ 3412 fcfp = fcftab->table; 3413 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 3414 if (fcfp->state == FCFI_STATE_FREE) { 3415 continue; 3416 } 3417 3418 /* Adjust the freshness flag */ 3419 if (fcfp->generation == fcftab->generation) { 3420 fcfp->flag |= EMLXS_FCFI_FRESH; 3421 } else { 3422 fcfp->flag &= ~EMLXS_FCFI_FRESH; 3423 } 3424 3425 /* Clear the failed bit */ 3426 fcfp->flag &= ~EMLXS_FCFI_FAILED; 3427 3428 /* Free all stale unselected entries now */ 3429 if (!(fcfp->flag & EMLXS_FCFI_FRESH) && 3430 !(fcfp->flag & EMLXS_FCFI_SELECTED)) { 3431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3432 "fcftab_read_cmpl_action:%d %s. " 3433 "FCF stale. Freeing FCF.", 3434 fcfp->fcf_index, 3435 emlxs_fcfi_state_xlate(fcfp->state)); 3436 3437 (void) emlxs_fcfi_free(port, fcfp); 3438 continue; 3439 } 3440 } 3441 3442 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, 3443 FCF_REASON_EVENT, evt, arg1); 3444 3445 return (rval); 3446 3447 } /* emlxs_fcftab_read_cmpl_action() */ 3448 3449 3450 static FCFIobj_t * 3451 emlxs_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn) 3452 { 3453 emlxs_hba_t *hba = HBA; 3454 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3455 FCFIobj_t *fcfp; 3456 FCFIobj_t *fcfp1; 3457 uint32_t mask; 3458 uint32_t viable; 3459 uint32_t i; 3460 uint32_t j; 3461 uint32_t rnum; 3462 timespec_t time; 3463 FCFIobj_t **fcf_table; 3464 uint32_t fcf_table_count; 3465 3466 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 3467 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH| 3468 EMLXS_FCFI_FAILED|EMLXS_FCFI_SELECTED); 3469 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 3470 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH); 3471 3472 /* Tag & count viable entries */ 3473 fcf_table_count = 0; 3474 fcfp = 0; 3475 fcfp1 = fcftab->table; 3476 for (i = 0; i < fcftab->table_count; i++, fcfp1++) { 3477 if (fcfp1->state == FCFI_STATE_FREE) { 3478 fcfp1->flag &= ~EMLXS_FCFI_TAGGED; 3479 continue; 3480 } 3481 3482 if ((fcfp1->flag & mask) != viable) { 3483 fcfp1->flag &= ~EMLXS_FCFI_TAGGED; 3484 continue; 3485 } 3486 3487 if (fabric_wwn && 3488 bcmp(fabric_wwn, 3489 fcfp1->fcf_rec.fabric_name_identifier, 8)) { 3490 fcfp1->flag &= ~EMLXS_FCFI_TAGGED; 3491 continue; 3492 } 3493 3494 fcfp1->flag |= EMLXS_FCFI_TAGGED; 3495 fcfp = fcfp1; 3496 fcf_table_count++; 3497 } 3498 3499 if (fcf_table_count == 0) { 3500 return (NULL); 3501 } 3502 3503 if (fcf_table_count == 1) { 3504 return (fcfp); 3505 } 3506 3507 /* We found more than one viable entry */ 3508 3509 fcf_table = (FCFIobj_t **)kmem_zalloc( 3510 (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP); 3511 3512 /* Find the highest priority tagged entry(s) */ 3513 for (i = 0; i < fcf_table_count; i++) { 3514 fcfp = 0; 3515 fcfp1 = fcftab->table; 3516 for (j = 0; j < fcftab->table_count; j++, fcfp1++) { 3517 if (!(fcfp1->flag & EMLXS_FCFI_TAGGED)) { 3518 continue; 3519 } 3520 3521 if (!fcfp || 3522 (fcfp1->priority > fcfp->priority)) { 3523 fcfp = fcfp1; 3524 } 3525 } 3526 3527 if (fcf_table[0] && 3528 (fcf_table[0]->priority > fcfp->priority)) { 3529 break; 3530 } 3531 3532 fcfp->flag &= ~EMLXS_FCFI_TAGGED; 3533 fcf_table[i] = fcfp; 3534 } 3535 3536 /* If more than one entry has the highest priority, */ 3537 /* then randomly select one of the highest. */ 3538 if (i > 1) { 3539 /* Pick a random number from 0 to (i-1) */ 3540 /* This algorithm uses the lower 16 bits of the nanosecond */ 3541 /* clock to determine the value */ 3542 bzero(&time, sizeof (timespec_t)); 3543 gethrestime(&time); 3544 rnum = (uint32_t)(time.tv_nsec & 0xFFFF); 3545 3546 fcfp = fcf_table[(rnum%i)]; 3547 } else { 3548 fcfp = fcf_table[0]; 3549 } 3550 3551 /* Free the priority table */ 3552 kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count)); 3553 3554 return (fcfp); 3555 3556 } /* emlxs_fcftab_fcfi_select() */ 3557 3558 3559 /*ARGSUSED*/ 3560 static void 3561 emlxs_fcftab_process(emlxs_port_t *port) 3562 { 3563 emlxs_hba_t *hba = HBA; 3564 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3565 FCFIobj_t *fcfp; 3566 FCFIobj_t *prev_fcfp; 3567 uint32_t i; 3568 uint32_t j; 3569 uint32_t count; 3570 uint32_t mask; 3571 uint32_t viable; 3572 emlxs_config_t *cfg = &CFG; 3573 3574 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 3575 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH| 3576 EMLXS_FCFI_FAILED); 3577 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 3578 EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH); 3579 3580 /* Deselection process */ 3581 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { 3582 fcfp = fcftab->fcfi[i]; 3583 3584 if (!fcfp) { 3585 continue; 3586 } 3587 3588 /* Check if entry is viable */ 3589 if ((fcfp->flag & mask) == viable) { 3590 if (fcfp->offline_timer) { 3591 fcfp->offline_timer = 0; 3592 3593 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3594 "fcftab_process:%d fcfi=%d %s. " 3595 "FCF viable. Offline timer disabled.", 3596 i, fcfp->fcf_index, 3597 emlxs_fcfi_state_xlate(fcfp->state), 3598 cfg[CFG_FCF_FAILOVER_DELAY].current); 3599 } 3600 continue; 3601 } 3602 3603 /* Previous entry is no longer viable */ 3604 3605 /* If FCF is still online */ 3606 if (fcfp->state > FCFI_STATE_OFFLINE) { 3607 if (fcfp->offline_timer == 0) { 3608 /* Set the offline timer */ 3609 fcfp->offline_timer = hba->timer_tics + 3610 cfg[CFG_FCF_FAILOVER_DELAY].current; 3611 3612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3613 "fcftab_process:%d fcfi=%d %s. " 3614 "No longer viable. " 3615 "Offlining FCF (%d secs).", 3616 i, fcfp->fcf_index, 3617 emlxs_fcfi_state_xlate(fcfp->state), 3618 cfg[CFG_FCF_FAILOVER_DELAY].current); 3619 } 3620 continue; 3621 } 3622 3623 /* Deselect it */ 3624 fcfp->flag &= ~EMLXS_FCFI_SELECTED; 3625 3626 if (!(fcfp->flag & EMLXS_FCFI_FRESH)) { 3627 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3628 "fcftab_process:%d fcfi=%d %s. " 3629 "No longer viable. Freeing FCF.", 3630 i, fcfp->fcf_index, 3631 emlxs_fcfi_state_xlate(fcfp->state)); 3632 3633 (void) emlxs_fcfi_free(port, fcfp); 3634 } else { 3635 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3636 "fcftab_process:%d fcfi=%d %s. " 3637 "No longer viable. FCF deselected.", 3638 i, fcfp->fcf_index, 3639 emlxs_fcfi_state_xlate(fcfp->state)); 3640 } 3641 } 3642 3643 /* Reselection process */ 3644 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { 3645 prev_fcfp = fcftab->fcfi[i]; 3646 fcftab->fcfi[i] = NULL; 3647 3648 /* If no previous selection, then make new one */ 3649 if (!prev_fcfp) { 3650 /* Select an fcf on any fabric */ 3651 fcfp = emlxs_fcftab_fcfi_select(port, 0); 3652 3653 if (fcfp) { 3654 fcfp->flag |= EMLXS_FCFI_SELECTED; 3655 fcftab->fcfi[i] = fcfp; 3656 3657 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3658 "fcftab_process:%d fcfi=%d %s. " 3659 "New FCF selected.", 3660 i, fcfp->fcf_index, 3661 emlxs_fcfi_state_xlate(fcfp->state)); 3662 } else { 3663 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3664 "fcftab_process:%d. No FCF available.", 3665 i); 3666 } 3667 continue; 3668 } 3669 3670 /* If previous entry is still selected, keep it */ 3671 if (prev_fcfp->flag & EMLXS_FCFI_SELECTED) { 3672 fcfp = prev_fcfp; 3673 fcftab->fcfi[i] = fcfp; 3674 3675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3676 "fcftab_process:%d fcfi=%d %s. " 3677 "FCF still selected.", 3678 i, fcfp->fcf_index, 3679 emlxs_fcfi_state_xlate(fcfp->state)); 3680 continue; 3681 } 3682 3683 /* Previous entry is no longer selected */ 3684 3685 /* Select a new fcf from same fabric */ 3686 fcfp = emlxs_fcftab_fcfi_select(port, 3687 (char *)prev_fcfp->fcf_rec.fabric_name_identifier); 3688 3689 if (fcfp) { 3690 fcfp->flag |= EMLXS_FCFI_SELECTED; 3691 fcftab->fcfi[i] = fcfp; 3692 3693 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3694 "fcftab_process:%d fcfi=%d %s. " 3695 "New FCF, same fabric selected.", 3696 i, fcfp->fcf_index, 3697 emlxs_fcfi_state_xlate(fcfp->state)); 3698 continue; 3699 } 3700 3701 /* Select fcf from any fabric */ 3702 fcfp = emlxs_fcftab_fcfi_select(port, 0); 3703 3704 if (fcfp) { 3705 fcfp->flag |= EMLXS_FCFI_SELECTED; 3706 fcftab->fcfi[i] = fcfp; 3707 3708 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3709 "fcftab_process:%d fcfi=%d %s. " 3710 "New FCF, new fabric selected.", 3711 i, fcfp->fcf_index, 3712 emlxs_fcfi_state_xlate(fcfp->state)); 3713 continue; 3714 } 3715 3716 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3717 "fcftab_process:%d. No FCF available.", 3718 i); 3719 } 3720 3721 /* Pack entries */ 3722 count = 0; 3723 for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { 3724 if (fcftab->fcfi[i]) { 3725 count++; 3726 continue; 3727 } 3728 3729 for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) { 3730 if (fcftab->fcfi[j] == NULL) { 3731 continue; 3732 } 3733 3734 fcftab->fcfi[i] = fcftab->fcfi[j]; 3735 fcftab->fcfi[j] = NULL; 3736 count++; 3737 break; 3738 } 3739 3740 if (j == FCFTAB_MAX_FCFI_COUNT) { 3741 break; 3742 } 3743 } 3744 fcftab->fcfi_count = count; 3745 3746 return; 3747 3748 } /* emlxs_fcftab_process() */ 3749 3750 3751 3752 /*ARGSUSED*/ 3753 static uint32_t 3754 emlxs_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt, 3755 void *arg1) 3756 { 3757 emlxs_hba_t *hba = HBA; 3758 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3759 FCFIobj_t *fcfp; 3760 uint32_t rval = 0; 3761 uint32_t i; 3762 uint32_t offline_count = 0; 3763 uint32_t online_count = 0; 3764 3765 if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE) { 3766 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3767 "fcftab_fcfi_online_action: %s:%s arg=%p. " 3768 "Invalid state. Terminated.", 3769 emlxs_fcftab_state_xlate(fcftab->state), 3770 emlxs_fcf_event_xlate(evt), arg1); 3771 return (1); 3772 } 3773 3774 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 3775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3776 "fcftab_fcfi_online_action: %s:%s arg=%p flag=%x. " 3777 "Handling request.", 3778 emlxs_fcftab_state_xlate(fcftab->state), 3779 emlxs_fcf_event_xlate(evt), arg1, 3780 fcftab->flag); 3781 3782 rval = emlxs_fcftab_req_handler(port, arg1); 3783 return (rval); 3784 } 3785 3786 emlxs_fcftab_process(port); 3787 3788 for (i = 0; i < fcftab->fcfi_count; i++) { 3789 fcfp = fcftab->fcfi[i]; 3790 3791 if (fcfp->offline_timer == 0) { 3792 online_count++; 3793 3794 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3795 "fcftab_fcfi_online_action: fcfi_count=%d. " 3796 "Onlining FCF:%d.", 3797 fcftab->fcfi_count, 3798 fcfp->fcf_index); 3799 3800 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE, 3801 fcfp); 3802 } else { 3803 offline_count++; 3804 3805 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3806 "fcftab_fcfi_online_action: fcfi_count=%d. " 3807 "Offlining FCF:%d.", 3808 fcftab->fcfi_count, 3809 fcfp->fcf_index); 3810 } 3811 } 3812 3813 if (offline_count) { 3814 /* Wait for FCF's to go offline */ 3815 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE, 3816 FCF_REASON_EVENT, evt, arg1); 3817 3818 /* Service timer now */ 3819 emlxs_fcftab_offline_timer(hba); 3820 3821 return (rval); 3822 } 3823 3824 if (!online_count) { 3825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3826 "fcftab_fcfi_online_action: fcfi_count=%d.", 3827 fcftab->fcfi_count); 3828 } 3829 3830 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE_CMPL, 3831 FCF_REASON_EVENT, evt, arg1); 3832 3833 return (rval); 3834 3835 } /* emlxs_fcftab_fcfi_online_action() */ 3836 3837 3838 /*ARGSUSED*/ 3839 static uint32_t 3840 emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt, 3841 void *arg1) 3842 { 3843 emlxs_hba_t *hba = HBA; 3844 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3845 uint32_t rval; 3846 3847 if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE_CMPL) { 3848 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3849 "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p. " 3850 "Invalid state. Terminated.", 3851 emlxs_fcftab_state_xlate(fcftab->state), 3852 emlxs_fcf_event_xlate(evt), arg1); 3853 return (1); 3854 } 3855 3856 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 3857 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3858 "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p flag=%x. " 3859 "Handling request.", 3860 emlxs_fcftab_state_xlate(fcftab->state), 3861 emlxs_fcf_event_xlate(evt), arg1, 3862 fcftab->flag); 3863 3864 rval = emlxs_fcftab_req_handler(port, arg1); 3865 return (rval); 3866 } 3867 3868 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3869 "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p", 3870 emlxs_fcftab_state_xlate(fcftab->state), 3871 emlxs_fcf_event_xlate(evt), arg1); 3872 3873 rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE, 3874 FCF_REASON_EVENT, evt, arg1); 3875 3876 return (rval); 3877 3878 } /* emlxs_fcftab_fcfi_online_cmpl_action() */ 3879 3880 3881 /*ARGSUSED*/ 3882 static uint32_t 3883 emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt, 3884 void *arg1) 3885 { 3886 emlxs_hba_t *hba = HBA; 3887 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3888 FCFIobj_t *fcfp; 3889 uint32_t rval; 3890 int32_t i; 3891 uint32_t fcfi_offline; 3892 3893 if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE) { 3894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3895 "fcftab_fcfi_offline_action: %s:%s arg=%p. " 3896 "Invalid state. Terminated.", 3897 emlxs_fcftab_state_xlate(fcftab->state), 3898 emlxs_fcf_event_xlate(evt), arg1); 3899 return (1); 3900 } 3901 3902 /* Check for FCF's going offline */ 3903 fcfi_offline = 0; 3904 for (i = 0; i < fcftab->fcfi_count; i++) { 3905 fcfp = fcftab->fcfi[i]; 3906 3907 if (fcfp->state <= FCFI_STATE_OFFLINE) { 3908 continue; 3909 } 3910 3911 if (fcfp->offline_timer || 3912 (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { 3913 fcfi_offline++; 3914 } 3915 } 3916 3917 if (fcfi_offline) { 3918 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3919 "fcftab_fcfi_offline_action: %s:%s arg=%p " 3920 "fcfi_offline=%d. Terminated.", 3921 emlxs_fcftab_state_xlate(fcftab->state), 3922 emlxs_fcf_event_xlate(evt), arg1, 3923 fcfi_offline); 3924 3925 return (0); 3926 } 3927 3928 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3929 "fcftab_fcfi_offline_action: %s:%s arg=%p.", 3930 emlxs_fcftab_state_xlate(fcftab->state), 3931 emlxs_fcf_event_xlate(evt), arg1); 3932 3933 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE_CMPL, 3934 FCF_REASON_EVENT, evt, arg1); 3935 return (rval); 3936 3937 } /* emlxs_fcftab_fcfi_offline_action() */ 3938 3939 3940 /*ARGSUSED*/ 3941 static uint32_t 3942 emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt, 3943 void *arg1) 3944 { 3945 emlxs_hba_t *hba = HBA; 3946 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3947 uint32_t rval; 3948 3949 if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE_CMPL) { 3950 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3951 "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. " 3952 "Invalid state. Terminated.", 3953 emlxs_fcftab_state_xlate(fcftab->state), 3954 emlxs_fcf_event_xlate(evt), arg1); 3955 return (1); 3956 } 3957 3958 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 3959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 3960 "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. " 3961 "Handling request.", 3962 emlxs_fcftab_state_xlate(fcftab->state), 3963 emlxs_fcf_event_xlate(evt), arg1); 3964 3965 rval = emlxs_fcftab_req_handler(port, arg1); 3966 return (rval); 3967 } 3968 3969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3970 "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p.", 3971 emlxs_fcftab_state_xlate(fcftab->state), 3972 emlxs_fcf_event_xlate(evt), arg1); 3973 3974 rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, 3975 FCF_REASON_EVENT, evt, arg1); 3976 3977 return (rval); 3978 3979 } /* emlxs_fcftab_fcfi_offline_cmpl_action() */ 3980 3981 3982 /*ARGSUSED*/ 3983 static uint32_t 3984 emlxs_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt, 3985 void *arg1) 3986 { 3987 emlxs_hba_t *hba = HBA; 3988 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 3989 uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); 3990 FCFIobj_t *fcfp; 3991 uint32_t rval = 0; 3992 3993 if (evt != FCF_EVENT_FCF_FOUND) { 3994 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 3995 "fcftab_found_evt_action: %s:%s fcf_index=%d. " 3996 "Invalid event type. Terminated.", 3997 emlxs_fcftab_state_xlate(fcftab->state), 3998 emlxs_fcf_event_xlate(evt), 3999 fcf_index); 4000 4001 return (1); 4002 } 4003 4004 switch (fcftab->state) { 4005 case FCFTAB_STATE_SOLICIT: 4006 case FCFTAB_STATE_SOLICIT_CMPL: 4007 case FCFTAB_STATE_READ: 4008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4009 "fcftab_found_evt_action: %s:%s fcf_index=%d gen=%x. " 4010 "Terminated.", 4011 emlxs_fcftab_state_xlate(fcftab->state), 4012 emlxs_fcf_event_xlate(evt), 4013 fcf_index, fcftab->generation); 4014 break; 4015 4016 /* case FCFTAB_STATE_FCFI_OFFLINE: */ 4017 default: 4018 4019 /* Scan for matching fcf index in table */ 4020 fcfp = emlxs_fcfi_find(port, 0, &fcf_index); 4021 4022 if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) { 4023 4024 /* Trigger table read */ 4025 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4026 fcftab->flag |= EMLXS_FCFTAB_READ_REQ; 4027 fcftab->generation++; 4028 4029 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4030 "fcftab_found_evt_action: %s:%s fcf_index=%d " 4031 "gen=%x. Read FCF table.", 4032 emlxs_fcftab_state_xlate(fcftab->state), 4033 emlxs_fcf_event_xlate(evt), 4034 fcf_index, fcftab->generation); 4035 4036 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, 4037 FCF_REASON_EVENT, evt, arg1); 4038 4039 break; 4040 } 4041 4042 /* Check if we need more FCF's */ 4043 if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) { 4044 4045 /* Trigger table read */ 4046 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4047 fcftab->flag |= EMLXS_FCFTAB_READ_REQ; 4048 fcftab->generation++; 4049 4050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4051 "fcftab_found_evt_action: %s:%s fcf_index=%d " 4052 "gen=%x fcfi_online=%d. Read FCF table.", 4053 emlxs_fcftab_state_xlate(fcftab->state), 4054 emlxs_fcf_event_xlate(evt), 4055 fcf_index, fcftab->generation, 4056 fcftab->fcfi_online); 4057 4058 rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, 4059 FCF_REASON_EVENT, evt, arg1); 4060 4061 break; 4062 } 4063 4064 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4065 "fcftab_found_evt_action: %s:%s fcfi=%d. " 4066 "FCF not needed. Terminated.", 4067 emlxs_fcftab_state_xlate(fcftab->state), 4068 emlxs_fcf_event_xlate(evt), 4069 fcf_index); 4070 4071 break; 4072 } 4073 4074 return (rval); 4075 4076 } /* emlxs_fcftab_found_evt_action() */ 4077 4078 4079 /*ARGSUSED*/ 4080 static uint32_t 4081 emlxs_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt, 4082 void *arg1) 4083 { 4084 emlxs_hba_t *hba = HBA; 4085 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4086 FCFIobj_t *fcfp; 4087 uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); 4088 emlxs_port_t *vport; 4089 VPIobj_t *vpip; 4090 uint32_t i; 4091 uint32_t rval; 4092 4093 if (evt != FCF_EVENT_FCF_LOST) { 4094 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4095 "fcftab_lost_evt_action: %s:%s fcf_index=%d. " 4096 "Invalid event type. Terminated", 4097 emlxs_fcftab_state_xlate(fcftab->state), 4098 emlxs_fcf_event_xlate(evt), 4099 fcf_index); 4100 4101 return (1); 4102 } 4103 4104 /* Scan for matching fcf index in table */ 4105 fcfp = emlxs_fcfi_find(port, 0, &fcf_index); 4106 4107 if (!fcfp) { 4108 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4109 "fcftab_lost_evt_action: %s:%s fcf_index=%d. " 4110 "FCF not found. Terminated.", 4111 emlxs_fcftab_state_xlate(fcftab->state), 4112 emlxs_fcf_event_xlate(evt), 4113 fcf_index); 4114 4115 return (0); 4116 } 4117 4118 if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) { 4119 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4120 "fcftab_changed_evt_action: %s:%s fcf_index=%d. " 4121 "FCF not selected. Terminated.", 4122 emlxs_fcftab_state_xlate(fcftab->state), 4123 emlxs_fcf_event_xlate(evt), 4124 fcf_index); 4125 4126 return (0); 4127 } 4128 4129 /* Offline VPI's of this FCFI */ 4130 for (i = 0; i <= hba->vpi_max; i++) { 4131 vport = &VPORT(i); 4132 vpip = &vport->VPIobj; 4133 4134 if ((vpip->state == VPI_STATE_OFFLINE) || 4135 (vpip->vfip->fcfp != fcfp)) { 4136 continue; 4137 } 4138 4139 /* Fabric logo is implied */ 4140 vpip->flag &= ~EMLXS_VPI_LOGI; 4141 if (vpip->flag & EMLXS_VPI_VFI_LOGI) { 4142 vpip->flag &= ~EMLXS_VPI_VFI_LOGI; 4143 4144 if (vpip->vfip->logi_count > 0) { 4145 vpip->vfip->logi_count--; 4146 } 4147 } 4148 4149 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4150 "fcftab_lost_evt_action: %s:%s fcf_index=%d gen=%x. " 4151 "Offlining VPI:%d.", 4152 emlxs_fcftab_state_xlate(fcftab->state), 4153 emlxs_fcf_event_xlate(evt), 4154 fcf_index, fcftab->generation, 4155 vpip->VPI); 4156 4157 (void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); 4158 } 4159 4160 switch (fcftab->state) { 4161 case FCFTAB_STATE_SOLICIT: 4162 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4163 "fcftab_lost_evt_action: %s gen=%x. " 4164 "Already soliciting. Terminated.", 4165 emlxs_fcftab_state_xlate(fcftab->state), 4166 fcftab->generation); 4167 break; 4168 4169 default: 4170 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4171 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 4172 fcftab->generation++; 4173 4174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4175 "fcftab_lost_evt_action: %s gen=%x. Soliciting.", 4176 emlxs_fcftab_state_xlate(fcftab->state), 4177 fcftab->generation); 4178 4179 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 4180 FCF_REASON_EVENT, evt, arg1); 4181 break; 4182 } 4183 4184 return (rval); 4185 4186 } /* emlxs_fcftab_lost_evt_action() */ 4187 4188 4189 /*ARGSUSED*/ 4190 static uint32_t 4191 emlxs_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt, 4192 void *arg1) 4193 { 4194 emlxs_hba_t *hba = HBA; 4195 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4196 FCFIobj_t *fcfp; 4197 uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); 4198 uint32_t rval; 4199 4200 if (evt != FCF_EVENT_FCF_CHANGED) { 4201 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4202 "fcftab_changed_evt_action: %s:%s fcf_index=%d. " 4203 "Invalid event type. Terminated", 4204 emlxs_fcftab_state_xlate(fcftab->state), 4205 emlxs_fcf_event_xlate(evt), 4206 fcf_index); 4207 4208 return (1); 4209 } 4210 4211 /* Scan for matching fcf index in table */ 4212 fcfp = emlxs_fcfi_find(port, 0, &fcf_index); 4213 4214 if (!fcfp) { 4215 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4216 "fcftab_changed_evt_action: %s:%s fcf_index=%d. " 4217 "FCFI not found. Terminated.", 4218 emlxs_fcftab_state_xlate(fcftab->state), 4219 emlxs_fcf_event_xlate(evt), 4220 fcf_index); 4221 4222 return (1); 4223 } 4224 4225 if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) { 4226 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4227 "fcftab_changed_evt_action: %s:%s fcf_index=%d. " 4228 "FCFI not selected. Terminated.", 4229 emlxs_fcftab_state_xlate(fcftab->state), 4230 emlxs_fcf_event_xlate(evt), 4231 fcf_index); 4232 4233 return (1); 4234 } 4235 4236 switch (fcftab->state) { 4237 case FCFTAB_STATE_SOLICIT: 4238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4239 "fcftab_changed_evt_action: %s gen=%x. " 4240 "Already soliciting. Terminated.", 4241 emlxs_fcftab_state_xlate(fcftab->state), 4242 fcftab->generation); 4243 break; 4244 4245 default: 4246 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4247 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 4248 fcftab->generation++; 4249 4250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4251 "fcftab_changed_evt_action: %s gen=%x. Soliciting.", 4252 emlxs_fcftab_state_xlate(fcftab->state), 4253 fcftab->generation); 4254 4255 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 4256 FCF_REASON_EVENT, evt, arg1); 4257 break; 4258 } 4259 4260 return (rval); 4261 4262 } /* emlxs_fcftab_changed_evt_action() */ 4263 4264 4265 /*ARGSUSED*/ 4266 static uint32_t 4267 emlxs_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index) 4268 { 4269 emlxs_hba_t *hba = HBA; 4270 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4271 MAILBOXQ *mbq; 4272 MAILBOX4 *mb4; 4273 MATCHMAP *mp = NULL; 4274 uint32_t rval; 4275 4276 IOCTL_FCOE_DELETE_FCF_TABLE *fcf; 4277 mbox_req_hdr_t *hdr_req; 4278 4279 if (fcf_index >= fcftab->fcfi_count) { 4280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4281 "fcftab_fcf_delete:%d failed. Out of range.", 4282 fcf_index); 4283 4284 return (1); 4285 } 4286 4287 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 4288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4289 "fcftab_fcf_delete:%d failed. Unable to allocate mailbox.", 4290 fcf_index); 4291 4292 return (1); 4293 } 4294 4295 mb4 = (MAILBOX4*)mbq; 4296 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 4297 4298 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 4299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4300 "fcftab_fcf_delete:%d failed. Unable to allocate buffer.", 4301 fcf_index); 4302 4303 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4304 return (1); 4305 } 4306 bzero(mp->virt, mp->size); 4307 4308 mbq->nonembed = (void *)mp; 4309 mbq->mbox_cmpl = NULL; 4310 mbq->context = (void *)((uintptr_t)fcf_index); 4311 mbq->port = (void *)port; 4312 4313 mb4->un.varSLIConfig.be.embedded = 0; 4314 mb4->mbxCommand = MBX_SLI_CONFIG; 4315 mb4->mbxOwner = OWN_HOST; 4316 4317 hdr_req = (mbox_req_hdr_t *)mp->virt; 4318 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 4319 hdr_req->opcode = FCOE_OPCODE_DELETE_FCF_TABLE; 4320 hdr_req->timeout = 0; 4321 hdr_req->req_length = sizeof (IOCTL_FCOE_DELETE_FCF_TABLE); 4322 4323 fcf = (IOCTL_FCOE_DELETE_FCF_TABLE *)(hdr_req + 1); 4324 fcf->params.request.fcf_count = 1; 4325 fcf->params.request.fcf_indexes[0] = (uint16_t)fcf_index; 4326 4327 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4328 "fcftab_fcf_delete:%d.", 4329 fcf_index); 4330 4331 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 4332 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 4333 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4334 "fcftab_fcf_delete:%d failed. Unable to send request.", 4335 fcf_index); 4336 4337 if (mp) { 4338 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 4339 } 4340 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4341 4342 return (1); 4343 } 4344 4345 return (0); 4346 4347 4348 } /* emlxs_fcftab_fcf_delete() */ 4349 4350 4351 /*ARGSUSED*/ 4352 static uint32_t 4353 emlxs_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt, 4354 void *arg1) 4355 { 4356 emlxs_hba_t *hba = HBA; 4357 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4358 FCFIobj_t *fcfp; 4359 uint32_t rval; 4360 uint32_t mask; 4361 uint32_t viable; 4362 uint32_t i; 4363 uint32_t count; 4364 4365 if (evt != FCF_EVENT_FCFTAB_FULL) { 4366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4367 "fcftab_full_evt_action: %s:%s arg=%p. " 4368 "Invalid event type. Terminated", 4369 emlxs_fcftab_state_xlate(fcftab->state), 4370 emlxs_fcf_event_xlate(evt), arg1); 4371 4372 return (1); 4373 } 4374 4375 if (fcftab->fcfi_online == FCFTAB_MAX_FCFI_COUNT) { 4376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4377 "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. " 4378 "Terminated.", 4379 emlxs_fcftab_state_xlate(fcftab->state), 4380 emlxs_fcf_event_xlate(evt), arg1, 4381 fcftab->fcfi_online); 4382 4383 return (0); 4384 } 4385 4386 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4387 "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. " 4388 "Cleaning table...", 4389 emlxs_fcftab_state_xlate(fcftab->state), 4390 emlxs_fcf_event_xlate(evt), arg1, 4391 fcftab->fcfi_online); 4392 4393 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 4394 EMLXS_FCFI_CONFIGURED); 4395 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 4396 EMLXS_FCFI_CONFIGURED); 4397 4398 count = 0; 4399 fcfp = fcftab->table; 4400 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4401 if (fcfp->state == FCFI_STATE_FREE) { 4402 continue; 4403 } 4404 4405 if (fcfp->flag & EMLXS_FCFI_SELECTED) { 4406 continue; 4407 } 4408 4409 if ((fcfp->flag & mask) == viable) { 4410 continue; 4411 } 4412 4413 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4414 "fcftab_full_evt_action: fcfi=%d %s flag=%x. " 4415 "Deleting FCF.", 4416 fcfp->fcf_index, 4417 emlxs_fcfi_state_xlate(fcfp->state), 4418 fcfp->flag); 4419 4420 (void) emlxs_fcfi_free(port, fcfp); 4421 4422 (void) emlxs_fcftab_fcf_delete(port, fcfp->fcf_index); 4423 4424 count++; 4425 } 4426 4427 if (!count) { 4428 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4429 "fcftab_full_evt_action: %s:%s arg=%p. " 4430 "All FCF's are viable. Terminated.", 4431 emlxs_fcftab_state_xlate(fcftab->state), 4432 emlxs_fcf_event_xlate(evt), arg1); 4433 4434 return (0); 4435 } 4436 4437 switch (fcftab->state) { 4438 case FCFTAB_STATE_SOLICIT: 4439 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4440 "fcftab_full_evt_action: %s gen=%x. " 4441 "Already soliciting. Terminated.", 4442 emlxs_fcftab_state_xlate(fcftab->state), 4443 fcftab->generation); 4444 break; 4445 4446 default: 4447 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4448 fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; 4449 fcftab->generation++; 4450 4451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4452 "fcftab_full_evt_action: %s gen=%x. Soliciting.", 4453 emlxs_fcftab_state_xlate(fcftab->state), 4454 fcftab->generation); 4455 4456 rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, 4457 FCF_REASON_EVENT, evt, arg1); 4458 break; 4459 } 4460 4461 return (rval); 4462 4463 } /* emlxs_fcftab_full_evt_action() */ 4464 4465 4466 /*ARGSUSED*/ 4467 static uint32_t 4468 emlxs_fcftab_online_action(emlxs_port_t *port, uint32_t evt, 4469 void *arg1) 4470 { 4471 emlxs_hba_t *hba = HBA; 4472 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4473 emlxs_config_t *cfg = &CFG; 4474 FCFIobj_t *fcfp; 4475 uint32_t rval; 4476 uint32_t mask; 4477 uint32_t viable; 4478 uint32_t i; 4479 uint32_t count = 0; 4480 4481 if (fcftab->state != FCFTAB_STATE_ONLINE) { 4482 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 4483 "fcftab_online_action: %s:%s arg=%p. " 4484 "Invalid state. Terminated.", 4485 emlxs_fcftab_state_xlate(fcftab->state), 4486 emlxs_fcf_event_xlate(evt), arg1); 4487 return (1); 4488 } 4489 4490 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 4491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4492 "fcftab_online_action: %s:%s arg=%p flag=%x. " 4493 "Handling request.", 4494 emlxs_fcftab_state_xlate(fcftab->state), 4495 emlxs_fcf_event_xlate(evt), arg1, 4496 fcftab->flag); 4497 4498 rval = emlxs_fcftab_req_handler(port, arg1); 4499 return (rval); 4500 } 4501 4502 if (fcftab->fcfi_online == 0) { 4503 mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 4504 EMLXS_FCFI_CONFIGURED); 4505 viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| 4506 EMLXS_FCFI_CONFIGURED); 4507 4508 /* Count viable FCF's in table */ 4509 count = 0; 4510 fcfp = fcftab->table; 4511 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4512 if (fcfp->state == FCFI_STATE_FREE) { 4513 continue; 4514 } 4515 4516 if ((fcfp->flag & mask) == viable) { 4517 count++; 4518 } 4519 } 4520 4521 if (count) { 4522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4523 "fcftab_online_action: %s:%s " 4524 "fcfi_online=0,%d,%d. Starting solicit timer.", 4525 emlxs_fcftab_state_xlate(fcftab->state), 4526 emlxs_fcf_event_xlate(evt), 4527 fcftab->fcfi_count, count); 4528 4529 /* Start the solicit timer */ 4530 fcftab->sol_timer = hba->timer_tics + 4531 cfg[CFG_FCF_RESOLICIT_DELAY].current; 4532 } else { 4533 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4534 "fcftab_online_action: %s:%s " 4535 "fcfi_online=0,%d,0. Wait for FCF event.", 4536 emlxs_fcftab_state_xlate(fcftab->state), 4537 emlxs_fcf_event_xlate(evt), 4538 fcftab->fcfi_count); 4539 } 4540 4541 if (hba->state > FC_LINK_DOWN) { 4542 mutex_enter(&EMLXS_PORT_LOCK); 4543 if (hba->state > FC_LINK_DOWN) { 4544 HBASTATS.LinkDown++; 4545 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); 4546 } 4547 hba->flag &= FC_LINKDOWN_MASK; 4548 hba->discovery_timer = 0; 4549 mutex_exit(&EMLXS_PORT_LOCK); 4550 4551 emlxs_log_link_event(port); 4552 } 4553 4554 return (0); 4555 } 4556 4557 if (hba->state < FC_LINK_UP) { 4558 mutex_enter(&EMLXS_PORT_LOCK); 4559 if (hba->state < FC_LINK_UP) { 4560 HBASTATS.LinkUp++; 4561 EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); 4562 } 4563 hba->discovery_timer = 4564 hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + 4565 cfg[CFG_DISC_TIMEOUT].current; 4566 mutex_exit(&EMLXS_PORT_LOCK); 4567 4568 emlxs_log_link_event(port); 4569 } 4570 4571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4572 "fcftab_online_action: %s:%s arg=%p fcfi_online=%d. Terminated.", 4573 emlxs_fcftab_state_xlate(fcftab->state), 4574 emlxs_fcf_event_xlate(evt), arg1, 4575 fcftab->fcfi_online); 4576 4577 return (0); 4578 4579 } /* emlxs_fcftab_online_action() */ 4580 4581 4582 /*ARGSUSED*/ 4583 static uint32_t 4584 emlxs_fcftab_offline_action(emlxs_port_t *port, uint32_t evt, 4585 void *arg1) 4586 { 4587 emlxs_hba_t *hba = HBA; 4588 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4589 uint32_t rval; 4590 4591 if (fcftab->state != FCFTAB_STATE_OFFLINE) { 4592 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 4593 "fcftab_offline_action: %s:%s arg=%p. " 4594 "Invalid state. Terminated.", 4595 emlxs_fcftab_state_xlate(fcftab->state), 4596 emlxs_fcf_event_xlate(evt), arg1); 4597 return (1); 4598 } 4599 4600 fcftab->flag &= ~EMLXS_FCFTAB_OFFLINE_REQ; 4601 4602 if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { 4603 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4604 "fcftab_offline_action: %s:%s arg=%p flag=%x. " 4605 "Handling request.", 4606 emlxs_fcftab_state_xlate(fcftab->state), 4607 emlxs_fcf_event_xlate(evt), arg1, 4608 fcftab->flag); 4609 4610 rval = emlxs_fcftab_req_handler(port, arg1); 4611 return (rval); 4612 } 4613 4614 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4615 "fcftab_offline_action: %s:%s arg=%p fcfi_online=%d. Terminated.", 4616 emlxs_fcftab_state_xlate(fcftab->state), 4617 emlxs_fcf_event_xlate(evt), arg1, 4618 fcftab->fcfi_online); 4619 4620 return (0); 4621 4622 } /* emlxs_fcftab_offline_action() */ 4623 4624 4625 /*ARGSUSED*/ 4626 static uint32_t 4627 emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt, 4628 void *arg1) 4629 { 4630 emlxs_hba_t *hba = HBA; 4631 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4632 FCFIobj_t *fcfp; 4633 uint32_t i; 4634 uint32_t online; 4635 4636 if (fcftab->state != FCFTAB_STATE_SHUTDOWN) { 4637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 4638 "fcftab_shutdown_action: %s:%s arg=%p. " 4639 "Invalid state. Terminated.", 4640 emlxs_fcftab_state_xlate(fcftab->state), 4641 emlxs_fcf_event_xlate(evt), arg1); 4642 return (1); 4643 } 4644 4645 fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; 4646 4647 if (fcftab->prev_state != FCFTAB_STATE_SHUTDOWN) { 4648 /* Offline all FCF's */ 4649 fcfp = fcftab->table; 4650 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4651 4652 if (fcfp->state <= FCFI_STATE_OFFLINE) { 4653 continue; 4654 } 4655 4656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4657 "fcftab_shutdown_action: fcfi=%d %s " 4658 "fcfi_online=%d. Offlining FCF.", 4659 fcfp->fcf_index, 4660 emlxs_fcfi_state_xlate(fcfp->state), 4661 fcftab->fcfi_online); 4662 4663 (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, 4664 fcfp); 4665 } 4666 4667 return (0); 4668 } 4669 4670 /* Check FCF state */ 4671 online = 0; 4672 fcfp = fcftab->table; 4673 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4674 4675 if (fcfp->state <= FCFI_STATE_OFFLINE) { 4676 continue; 4677 } 4678 4679 online++; 4680 } 4681 4682 if (online) { 4683 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4684 "fcftab_shutdown_action: %s:%s arg=%p. " 4685 "fcfi_online=%d,%d Terminated.", 4686 emlxs_fcftab_state_xlate(fcftab->state), 4687 emlxs_fcf_event_xlate(evt), arg1, 4688 online, fcftab->fcfi_online); 4689 4690 return (0); 4691 } 4692 4693 /* Free FCF table */ 4694 fcfp = fcftab->table; 4695 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4696 4697 if (fcfp->state == FCFI_STATE_FREE) { 4698 continue; 4699 } 4700 4701 (void) emlxs_fcfi_free(port, fcfp); 4702 } 4703 4704 /* Clean the selection table */ 4705 bzero(fcftab->fcfi, sizeof (fcftab->fcfi)); 4706 fcftab->fcfi_count = 0; 4707 4708 fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN; 4709 4710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 4711 "fcftab_shutdown_action: %s:%s arg=%p flag=%x fcfi_online=%d. " 4712 "Shutdown.", 4713 emlxs_fcftab_state_xlate(fcftab->state), 4714 emlxs_fcf_event_xlate(evt), arg1, 4715 fcftab->flag, fcftab->fcfi_online); 4716 4717 return (0); 4718 4719 } /* emlxs_fcftab_shutdown_action() */ 4720 4721 4722 4723 /* ************************************************************************** */ 4724 /* FCFI */ 4725 /* ************************************************************************** */ 4726 4727 static char * 4728 emlxs_fcfi_state_xlate(uint32_t state) 4729 { 4730 static char buffer[32]; 4731 uint32_t i; 4732 uint32_t count; 4733 4734 count = sizeof (emlxs_fcfi_state_table) / sizeof (emlxs_table_t); 4735 for (i = 0; i < count; i++) { 4736 if (state == emlxs_fcfi_state_table[i].code) { 4737 return (emlxs_fcfi_state_table[i].string); 4738 } 4739 } 4740 4741 (void) sprintf(buffer, "state=0x%x", state); 4742 return (buffer); 4743 4744 } /* emlxs_fcfi_state_xlate() */ 4745 4746 4747 static uint32_t 4748 emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 4749 void *arg1) 4750 { 4751 uint32_t rval; 4752 uint32_t(*func) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *); 4753 uint32_t index; 4754 uint32_t events; 4755 uint16_t state; 4756 4757 /* Convert event to action table index */ 4758 switch (evt) { 4759 case FCF_EVENT_STATE_ENTER: 4760 index = 0; 4761 break; 4762 case FCF_EVENT_FCFI_ONLINE: 4763 index = 1; 4764 break; 4765 case FCF_EVENT_FCFI_OFFLINE: 4766 index = 2; 4767 break; 4768 case FCF_EVENT_FCFI_PAUSE: 4769 index = 3; 4770 break; 4771 case FCF_EVENT_VFI_ONLINE: 4772 index = 4; 4773 break; 4774 case FCF_EVENT_VFI_OFFLINE: 4775 index = 5; 4776 break; 4777 default: 4778 return (1); 4779 } 4780 4781 events = FCFI_ACTION_EVENTS; 4782 state = fcfp->state; 4783 4784 index += (state * events); 4785 func = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *)) 4786 emlxs_fcfi_action_table[index]; 4787 4788 if (!func) { 4789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 4790 "fcfi:%d %s:%s arg=%p. No action. Terminated.", 4791 fcfp->fcf_index, 4792 emlxs_fcfi_state_xlate(fcfp->state), 4793 emlxs_fcf_event_xlate(evt), arg1); 4794 4795 return (1); 4796 } 4797 4798 rval = (func)(port, fcfp, evt, arg1); 4799 4800 return (rval); 4801 4802 } /* emlxs_fcfi_action() */ 4803 4804 4805 static uint32_t 4806 emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt, 4807 void *arg1) 4808 { 4809 FCFIobj_t *fcfp = NULL; 4810 VFIobj_t *vfip = NULL; 4811 uint32_t rval; 4812 4813 /* Filter events and acquire fcfi context */ 4814 switch (evt) { 4815 case FCF_EVENT_VFI_ONLINE: 4816 case FCF_EVENT_VFI_OFFLINE: 4817 vfip = (VFIobj_t *)arg1; 4818 4819 if (!vfip) { 4820 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 4821 "fcfi: %s arg=%p. Null VFI found. Terminated.", 4822 emlxs_fcf_event_xlate(evt), arg1); 4823 4824 return (1); 4825 } 4826 4827 fcfp = vfip->fcfp; 4828 if (!fcfp) { 4829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 4830 "fcfi: %s arg=%p. FCF not found. Terminated.", 4831 emlxs_fcf_event_xlate(evt), arg1); 4832 4833 return (1); 4834 } 4835 break; 4836 4837 case FCF_EVENT_FCFI_ONLINE: 4838 case FCF_EVENT_FCFI_OFFLINE: 4839 case FCF_EVENT_FCFI_PAUSE: 4840 fcfp = (FCFIobj_t *)arg1; 4841 if (!fcfp) { 4842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 4843 "fcfi: %s arg=%p. Null FCFI found. Terminated.", 4844 emlxs_fcf_event_xlate(evt), arg1); 4845 4846 return (1); 4847 } 4848 break; 4849 4850 default: 4851 return (1); 4852 } 4853 4854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 4855 "fcfi:%d %s:%s arg=%p", 4856 fcfp->fcf_index, 4857 emlxs_fcfi_state_xlate(fcfp->state), 4858 emlxs_fcf_event_xlate(evt), arg1); 4859 4860 rval = emlxs_fcfi_action(port, fcfp, evt, arg1); 4861 4862 return (rval); 4863 4864 } /* emlxs_fcfi_event() */ 4865 4866 4867 /* EMLXS_FCF_LOCK must be held to enter */ 4868 /*ARGSUSED*/ 4869 static uint32_t 4870 emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state, 4871 uint16_t reason, uint32_t explain, void *arg1) 4872 { 4873 uint32_t rval = 0; 4874 4875 if (state >= FCFI_ACTION_STATES) { 4876 return (1); 4877 } 4878 4879 if ((fcfp->state == state) && 4880 (reason != FCF_REASON_REENTER)) { 4881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 4882 "fcfi_state:%d %s:%s:0x%x arg=%p. " 4883 "State not changed. Terminated.", 4884 fcfp->fcf_index, 4885 emlxs_fcfi_state_xlate(state), 4886 emlxs_fcf_reason_xlate(reason), 4887 explain, arg1); 4888 4889 return (1); 4890 } 4891 4892 if (!reason) { 4893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 4894 "fcfi:%d %s-->%s arg=%p", 4895 fcfp->fcf_index, 4896 emlxs_fcfi_state_xlate(fcfp->state), 4897 emlxs_fcfi_state_xlate(state), arg1); 4898 } else if (reason == FCF_REASON_EVENT) { 4899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 4900 "fcfi:%d %s-->%s:%s:%s arg=%p", 4901 fcfp->fcf_index, 4902 emlxs_fcfi_state_xlate(fcfp->state), 4903 emlxs_fcfi_state_xlate(state), 4904 emlxs_fcf_reason_xlate(reason), 4905 emlxs_fcf_event_xlate(explain), arg1); 4906 } else if (explain) { 4907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 4908 "fcfi:%d %s-->%s:%s:0x%x arg=%p", 4909 fcfp->fcf_index, 4910 emlxs_fcfi_state_xlate(fcfp->state), 4911 emlxs_fcfi_state_xlate(state), 4912 emlxs_fcf_reason_xlate(reason), 4913 explain, arg1); 4914 } else { 4915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 4916 "fcfi:%d %s-->%s:%s arg=%p", 4917 fcfp->fcf_index, 4918 emlxs_fcfi_state_xlate(fcfp->state), 4919 emlxs_fcfi_state_xlate(state), 4920 emlxs_fcf_reason_xlate(reason), arg1); 4921 } 4922 4923 fcfp->prev_state = fcfp->state; 4924 fcfp->prev_reason = fcfp->reason; 4925 fcfp->state = state; 4926 fcfp->reason = reason; 4927 4928 rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1); 4929 4930 return (rval); 4931 4932 } /* emlxs_fcfi_state() */ 4933 4934 4935 static FCFIobj_t * 4936 emlxs_fcfi_alloc(emlxs_port_t *port) 4937 { 4938 emlxs_hba_t *hba = HBA; 4939 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4940 uint16_t i; 4941 FCFIobj_t *fcfp; 4942 4943 fcfp = fcftab->table; 4944 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4945 if (fcfp->state == FCFI_STATE_FREE) { 4946 4947 bzero(fcfp, sizeof (FCFIobj_t)); 4948 fcfp->index = i; 4949 fcfp->FCFI = 0xFFFF; 4950 4951 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, 4952 0, 0, 0); 4953 return (fcfp); 4954 } 4955 } 4956 4957 return (NULL); 4958 4959 } /* emlxs_fcfi_alloc() */ 4960 4961 4962 static uint32_t 4963 emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp) 4964 { 4965 uint32_t rval; 4966 4967 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0); 4968 4969 return (rval); 4970 4971 } /* emlxs_fcfi_free() */ 4972 4973 4974 static FCFIobj_t * 4975 emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index) 4976 { 4977 emlxs_hba_t *hba = HBA; 4978 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 4979 uint32_t i; 4980 uint32_t index; 4981 FCFIobj_t *fcfp; 4982 4983 if (fcfrec) { 4984 /* Check for a matching FCF index, fabric name, */ 4985 /* and mac address */ 4986 fcfp = fcftab->table; 4987 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 4988 if (fcfp->state == FCFI_STATE_FREE) { 4989 continue; 4990 } 4991 4992 if ((fcfp->fcf_index == fcfrec->fcf_index) && 4993 (bcmp((char *)fcfrec->fabric_name_identifier, 4994 fcfp->fcf_rec.fabric_name_identifier, 8) == 0) && 4995 (bcmp((char *)fcfrec->fcf_mac_address_hi, 4996 fcfp->fcf_rec.fcf_mac_address_hi, 4) == 0) && 4997 (bcmp((char *)fcfrec->fcf_mac_address_low, 4998 fcfp->fcf_rec.fcf_mac_address_low, 2) == 0)) { 4999 return (fcfp); 5000 } 5001 } 5002 5003 } else if (fcf_index) { 5004 /* Check for a matching FCF index only */ 5005 index = *fcf_index; 5006 fcfp = fcftab->table; 5007 for (i = 0; i < fcftab->table_count; i++, fcfp++) { 5008 if (fcfp->state == FCFI_STATE_FREE) { 5009 continue; 5010 } 5011 5012 if (fcfp->fcf_index == index) { 5013 return (fcfp); 5014 } 5015 } 5016 } 5017 5018 return (NULL); 5019 5020 } /* emlxs_fcfi_find() */ 5021 5022 5023 /*ARGSUSED*/ 5024 static uint32_t 5025 emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5026 void *arg1) 5027 { 5028 5029 if (fcfp->state != FCFI_STATE_FREE) { 5030 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5031 "fcfi_free_action:%d %s:%s arg=%p. " 5032 "Invalid state. Terminated.", 5033 fcfp->fcf_index, 5034 emlxs_fcfi_state_xlate(fcfp->state), 5035 emlxs_fcf_event_xlate(evt), arg1); 5036 return (1); 5037 } 5038 5039 if (fcfp->vfi_online) { 5040 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5041 "fcfi_free_action:%d flag=%x vfi_online=%d", 5042 fcfp->fcf_index, 5043 fcfp->flag, 5044 fcfp->vfi_online); 5045 } 5046 5047 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5048 "fcfi_free_action:%d flag=%x. FCF freed.", 5049 fcfp->fcf_index, 5050 fcfp->flag); 5051 5052 fcfp->flag = 0; 5053 5054 return (0); 5055 5056 } /* emlxs_fcfi_free_action() */ 5057 5058 5059 /*ARGSUSED*/ 5060 static uint32_t 5061 emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5062 void *arg1) 5063 { 5064 emlxs_hba_t *hba = HBA; 5065 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 5066 uint32_t rval; 5067 5068 if (fcfp->state != FCFI_STATE_OFFLINE) { 5069 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5070 "fcfi_offline_action:%d %s:%s arg=%p. " 5071 "Invalid state. Terminated.", 5072 fcfp->fcf_index, 5073 emlxs_fcfi_state_xlate(fcfp->state), 5074 emlxs_fcf_event_xlate(evt), arg1); 5075 return (1); 5076 } 5077 5078 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); 5079 5080 if (fcfp->prev_state == FCFI_STATE_FREE) { 5081 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5082 "fcfi_offline_action:%d fcfi_online=%d. Terminated.", 5083 fcfp->fcf_index, 5084 fcftab->fcfi_online); 5085 5086 return (0); 5087 } 5088 5089 if (fcfp->vfi_online) { 5090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5091 "fcfi_offline_action:%d vfi_online=%d.", 5092 fcfp->fcf_index, 5093 fcfp->vfi_online); 5094 } 5095 5096 if (fcfp->flag & EMLXS_FCFI_FCFTAB) { 5097 fcfp->flag &= ~EMLXS_FCFI_FCFTAB; 5098 5099 if (fcftab->fcfi_online) { 5100 fcftab->fcfi_online--; 5101 } 5102 } 5103 5104 /* Check if online was requested */ 5105 if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) { 5106 5107 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5108 "fcfi_offline_action:%d fcfi_online=%d. " 5109 "Online requested.", 5110 fcfp->fcf_index, 5111 fcftab->fcfi_online); 5112 5113 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, 5114 FCF_REASON_REQUESTED, 0, arg1); 5115 return (rval); 5116 } 5117 5118 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5119 "fcfi_offline_action:%d fcfi_online=%d. " 5120 "FCFI offline. Notifying fcftab.", 5121 fcfp->fcf_index, 5122 fcftab->fcfi_online); 5123 5124 /* Notify FCFTAB */ 5125 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp); 5126 5127 return (rval); 5128 5129 } /* emlxs_fcfi_offline_action() */ 5130 5131 5132 /*ARGSUSED*/ 5133 static uint32_t 5134 emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5135 uint32_t evt, void *arg1) 5136 { 5137 uint32_t rval; 5138 5139 if (evt != FCF_EVENT_VFI_ONLINE) { 5140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5141 "fcfi_vfi_online_evt_action:%d %s:%s arg=%p flag=%x. " 5142 "Invalid event type. Terminated.", 5143 fcfp->fcf_index, 5144 emlxs_fcfi_state_xlate(fcfp->state), 5145 emlxs_fcf_event_xlate(evt), arg1, 5146 fcfp->flag); 5147 return (1); 5148 } 5149 5150 switch (fcfp->state) { 5151 case FCFI_STATE_ONLINE: 5152 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5153 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " 5154 "Reentering online.", 5155 fcfp->fcf_index, 5156 fcfp->flag, 5157 fcfp->vfi_online); 5158 5159 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, 5160 FCF_REASON_REENTER, evt, arg1); 5161 break; 5162 5163 case FCFI_STATE_VFI_ONLINE: 5164 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5165 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " 5166 "Online cmpl.", 5167 fcfp->fcf_index, 5168 fcfp->flag, 5169 fcfp->vfi_online); 5170 5171 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL, 5172 FCF_REASON_EVENT, evt, arg1); 5173 break; 5174 5175 default: 5176 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5177 "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " 5178 "Terminated.", 5179 fcfp->fcf_index, 5180 fcfp->flag, 5181 fcfp->vfi_online); 5182 return (0); 5183 } 5184 5185 return (rval); 5186 5187 } /* emlxs_fcfi_vfi_online_evt_action() */ 5188 5189 5190 /*ARGSUSED*/ 5191 static uint32_t 5192 emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1) 5193 { 5194 uint32_t rval; 5195 5196 if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { 5197 return (0); 5198 } 5199 5200 if (fcfp->vfi_online != 0) { 5201 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { 5202 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED, 5203 FCF_REASON_REQUESTED, 0, arg1); 5204 } else { 5205 rval = emlxs_fcfi_state(port, fcfp, 5206 FCFI_STATE_VFI_OFFLINE, FCF_REASON_REQUESTED, 5207 0, arg1); 5208 } 5209 5210 } else if (fcfp->flag & EMLXS_FCFI_REG) { 5211 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, 5212 FCF_REASON_REQUESTED, 0, arg1); 5213 5214 } else { 5215 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, 5216 FCF_REASON_REQUESTED, 0, arg1); 5217 } 5218 5219 return (rval); 5220 5221 } /* emlxs_fcfi_offline_handler() */ 5222 5223 5224 /*ARGSUSED*/ 5225 static uint32_t 5226 emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5227 uint32_t evt, void *arg1) 5228 { 5229 uint32_t rval; 5230 VFIobj_t *vfip; 5231 5232 if (evt != FCF_EVENT_VFI_OFFLINE) { 5233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5234 "fcfi_vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. " 5235 "Invalid event type. Terminated.", 5236 fcfp->fcf_index, 5237 emlxs_fcfi_state_xlate(fcfp->state), 5238 emlxs_fcf_event_xlate(evt), arg1, 5239 fcfp->flag); 5240 return (1); 5241 } 5242 5243 vfip = (VFIobj_t *)arg1; 5244 vfip->fcfp = NULL; 5245 5246 switch (fcfp->state) { 5247 case FCFI_STATE_VFI_ONLINE: 5248 case FCFI_STATE_ONLINE: 5249 if (fcfp->vfi_online == 0) { 5250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5251 "fcfi_vfi_offline_evt_action:%d flag=%x " 5252 "vfi_online=%d. Offlining.", 5253 fcfp->fcf_index, 5254 fcfp->flag, fcfp->vfi_online); 5255 5256 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5257 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5258 5259 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 5260 } else { 5261 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5262 "fcfi_vfi_offline_evt_action:%d flag=%x " 5263 "vfi_online=%d. Terminated.", 5264 fcfp->fcf_index, 5265 fcfp->flag, fcfp->vfi_online); 5266 } 5267 break; 5268 5269 case FCFI_STATE_PAUSED: 5270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5271 "fcfi_vfi_offline_evt_action:%d flag=%x vfi_online=%d. " 5272 "Terminated.", 5273 fcfp->fcf_index, 5274 fcfp->flag, fcfp->vfi_online); 5275 break; 5276 5277 case FCFI_STATE_VFI_OFFLINE: 5278 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5279 "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.", 5280 fcfp->fcf_index, 5281 fcfp->flag); 5282 5283 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL, 5284 FCF_REASON_EVENT, evt, arg1); 5285 break; 5286 5287 case FCFI_STATE_VFI_OFFLINE_CMPL: 5288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5289 "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.", 5290 fcfp->fcf_index, 5291 fcfp->flag); 5292 5293 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL, 5294 FCF_REASON_REENTER, evt, arg1); 5295 break; 5296 5297 default: 5298 if (fcfp->vfi_online == 0) { 5299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5300 "fcfi_vfi_offline_evt_action:%d flag=%x " 5301 "vfi_online=%d. Offline requested.", 5302 fcfp->fcf_index, 5303 fcfp->flag, fcfp->vfi_online); 5304 5305 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5306 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5307 } else { 5308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5309 "fcfi_vfi_offline_evt_action:%d flag = %x " 5310 "vfi_online=%d. Terminated.", 5311 fcfp->fcf_index, 5312 fcfp->flag, fcfp->vfi_online); 5313 } 5314 return (0); 5315 } 5316 5317 return (rval); 5318 5319 } /* emlxs_fcfi_vfi_offline_evt_action() */ 5320 5321 5322 /*ARGSUSED*/ 5323 static uint32_t 5324 emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5325 uint32_t evt, void *arg1) 5326 { 5327 uint32_t rval = 0; 5328 5329 if (evt != FCF_EVENT_FCFI_ONLINE) { 5330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5331 "fcfi_online_evt_action:%d %s:%s arg=%p. " 5332 "Invalid event type. Terminated.", 5333 fcfp->fcf_index, 5334 emlxs_fcfi_state_xlate(fcfp->state), 5335 emlxs_fcf_event_xlate(evt), arg1); 5336 return (1); 5337 } 5338 5339 if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) { 5340 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5341 "fcfi_online_evt_action:%d. " 5342 "Online already requested. Terminated.", 5343 fcfp->fcf_index); 5344 return (1); 5345 } 5346 5347 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5348 fcfp->flag |= EMLXS_FCFI_ONLINE_REQ; 5349 5350 switch (fcfp->state) { 5351 case FCFI_STATE_OFFLINE: 5352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5353 "fcfi_online_evt_action:%d flag=%x. Initiating online.", 5354 fcfp->fcf_index, 5355 fcfp->flag); 5356 5357 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, 5358 FCF_REASON_EVENT, evt, arg1); 5359 break; 5360 5361 case FCFI_STATE_VFI_OFFLINE: 5362 case FCFI_STATE_PAUSED: 5363 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5364 "fcfi_online_evt_action:%d flag=%x. Initiating online.", 5365 fcfp->fcf_index, 5366 fcfp->flag); 5367 5368 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, 5369 FCF_REASON_EVENT, evt, arg1); 5370 break; 5371 5372 case FCFI_STATE_ONLINE: 5373 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5374 "fcfi_online_evt_action:%d flag=%x. Reentering online.", 5375 fcfp->fcf_index, 5376 fcfp->flag); 5377 5378 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, 5379 FCF_REASON_REENTER, evt, arg1); 5380 break; 5381 5382 default: 5383 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5384 "fcfi_online_evt_action:%d flag=%x. Terminated.", 5385 fcfp->fcf_index, 5386 fcfp->flag); 5387 break; 5388 } 5389 5390 return (rval); 5391 5392 } /* emlxs_fcfi_online_evt_action() */ 5393 5394 5395 /*ARGSUSED*/ 5396 static uint32_t 5397 emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5398 uint32_t evt, void *arg1) 5399 { 5400 emlxs_hba_t *hba = HBA; 5401 uint32_t i; 5402 uint32_t rval; 5403 VFIobj_t *vfip; 5404 5405 if (fcfp->state != FCFI_STATE_VFI_ONLINE) { 5406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5407 "fcfi_vfi_online_action:%d %s:%s arg=%p. " 5408 "Invalid state. Terminated.", 5409 fcfp->fcf_index, 5410 emlxs_fcfi_state_xlate(fcfp->state), 5411 emlxs_fcf_event_xlate(evt), arg1); 5412 return (1); 5413 } 5414 5415 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { 5416 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5417 "fcfi_vfi_online_action:%d. Offline requested.", 5418 fcfp->fcf_index); 5419 5420 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 5421 return (rval); 5422 } 5423 5424 if (fcfp->vfi_online > 0) { 5425 /* Waking up out after being paused */ 5426 5427 /* Find first VFI of this FCFI */ 5428 vfip = hba->sli.sli4.VFI_table; 5429 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { 5430 if (vfip->fcfp == fcfp) { 5431 break; 5432 } 5433 } 5434 5435 } else { 5436 5437 /* Find first available VFI */ 5438 vfip = hba->sli.sli4.VFI_table; 5439 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { 5440 if (vfip->fcfp == NULL) { 5441 vfip->fcfp = fcfp; 5442 break; 5443 } 5444 } 5445 } 5446 5447 if (i == hba->sli.sli4.VFICount) { 5448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5449 "fcfi_vfi_online_action:%d vfi_online=%d. " 5450 "No VFI found. Offlining.", 5451 fcfp->fcf_index, 5452 fcfp->vfi_online); 5453 5454 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5455 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5456 5457 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 5458 return (rval); 5459 } 5460 5461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5462 "fcfi_vfi_online_action:%d vfi_online=%d. Onlining VFI:%d.", 5463 fcfp->fcf_index, 5464 fcfp->vfi_online, 5465 vfip->VFI); 5466 5467 rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); 5468 5469 /* Wait for FCF_EVENT_VFI_ONLINE in return */ 5470 5471 return (rval); 5472 5473 } /* emlxs_fcfi_vfi_online_action() */ 5474 5475 5476 /*ARGSUSED*/ 5477 static uint32_t 5478 emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5479 uint32_t evt, void *arg1) 5480 { 5481 uint32_t rval; 5482 5483 if (fcfp->state != FCFI_STATE_VFI_ONLINE_CMPL) { 5484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5485 "fcfi_vfi_online_cmpl_action:%d %s:%s arg=%p. " 5486 "Invalid state. Terminated.", 5487 fcfp->fcf_index, 5488 emlxs_fcfi_state_xlate(fcfp->state), 5489 emlxs_fcf_event_xlate(evt), arg1); 5490 return (1); 5491 } 5492 5493 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5494 "fcfi_vfi_online_cmpl_action:%d. Going online.", 5495 fcfp->fcf_index); 5496 5497 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, 5498 FCF_REASON_EVENT, evt, arg1); 5499 5500 return (rval); 5501 5502 } /* emlxs_fcfi_vfi_online_cmpl_action() */ 5503 5504 5505 /*ARGSUSED*/ 5506 static uint32_t 5507 emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5508 void *arg1) 5509 { 5510 emlxs_hba_t *hba = HBA; 5511 VFIobj_t *vfip; 5512 uint32_t rval; 5513 int32_t i; 5514 5515 if (fcfp->state != FCFI_STATE_VFI_OFFLINE) { 5516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5517 "fcfi_vfi_offline_action:%d %s:%s arg=%p. " 5518 "Invalid state. Terminated.", 5519 fcfp->fcf_index, 5520 emlxs_fcfi_state_xlate(fcfp->state), 5521 emlxs_fcf_event_xlate(evt), arg1); 5522 5523 return (1); 5524 } 5525 5526 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { 5527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5528 "fcfi_vfi_offline_action:%d vfi_online=%d. Pausing.", 5529 fcfp->fcf_index, 5530 fcfp->vfi_online); 5531 5532 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED, 5533 FCF_REASON_EVENT, evt, arg1); 5534 5535 return (rval); 5536 } 5537 5538 if (fcfp->vfi_online == 0) { 5539 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5540 "fcfi_vfi_offline_action:%d. " 5541 "VFI already offline. Skipping VFI offline.", 5542 fcfp->fcf_index); 5543 5544 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, 5545 FCF_REASON_EVENT, evt, arg1); 5546 5547 return (rval); 5548 } 5549 5550 /* Offline VFI's of this FCFI */ 5551 for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) { 5552 vfip = &hba->sli.sli4.VFI_table[i]; 5553 5554 if ((vfip->fcfp != fcfp) || 5555 (vfip->state == VFI_STATE_OFFLINE) || 5556 (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { 5557 continue; 5558 } 5559 5560 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5561 "fcfi_vfi_offline_action:%d. Offlining VFI:%d", 5562 fcfp->fcf_index, 5563 vfip->VFI); 5564 5565 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip); 5566 } 5567 5568 /* Wait for FCF_EVENT_VFI_OFFLINE in return */ 5569 5570 return (0); 5571 5572 } /* emlxs_fcfi_vfi_offline_action() */ 5573 5574 5575 /*ARGSUSED*/ 5576 static uint32_t 5577 emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5578 void *arg1) 5579 { 5580 emlxs_hba_t *hba = HBA; 5581 VFIobj_t *vfip; 5582 int32_t i; 5583 5584 if (fcfp->state != FCFI_STATE_PAUSED) { 5585 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5586 "fcfi_paused_action:%d %s:%s arg=%p. " 5587 "Invalid state. Terminated.", 5588 fcfp->fcf_index, 5589 emlxs_fcfi_state_xlate(fcfp->state), 5590 emlxs_fcf_event_xlate(evt), arg1); 5591 5592 return (1); 5593 } 5594 5595 fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); 5596 5597 /* Pause all VFI's of this FCFI */ 5598 for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) { 5599 vfip = &hba->sli.sli4.VFI_table[i]; 5600 5601 if ((vfip->state == VFI_STATE_OFFLINE) || 5602 (vfip->state == VFI_STATE_PAUSED) || 5603 (vfip->fcfp != fcfp)) { 5604 continue; 5605 } 5606 5607 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5608 "fcfi_paused_action:%d vfi_online=%d. Pausing VFI:%d.", 5609 fcfp->fcf_index, 5610 fcfp->vfi_online, 5611 vfip->VFI); 5612 5613 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip); 5614 } 5615 5616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5617 "fcfi_paused_action:%d vfi_online=%d. FCFI paused.", 5618 fcfp->fcf_index, 5619 fcfp->vfi_online); 5620 5621 return (0); 5622 5623 } /* emlxs_fcfi_paused_action() */ 5624 5625 5626 /*ARGSUSED*/ 5627 static uint32_t 5628 emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5629 uint32_t evt, void *arg1) 5630 { 5631 uint32_t rval = 0; 5632 5633 if (fcfp->state != FCFI_STATE_VFI_OFFLINE_CMPL) { 5634 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5635 "fcfi_vfi_offline_cmpl_action:%d %s:%s arg=%p. " 5636 "Invalid state. Terminated.", 5637 fcfp->fcf_index, 5638 emlxs_fcfi_state_xlate(fcfp->state), 5639 emlxs_fcf_event_xlate(evt), arg1); 5640 return (1); 5641 } 5642 5643 if ((fcfp->vfi_online == 0) && 5644 (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { 5645 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5646 "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. " 5647 "Unregistering.", 5648 fcfp->fcf_index, 5649 fcfp->vfi_online); 5650 5651 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, 5652 FCF_REASON_EVENT, evt, arg1); 5653 } else { 5654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5655 "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. " 5656 "Terminated.", 5657 fcfp->fcf_index, 5658 fcfp->vfi_online); 5659 } 5660 5661 return (rval); 5662 5663 } /* emlxs_fcfi_vfi_offline_cmpl_action() */ 5664 5665 5666 /*ARGSUSED*/ 5667 static uint32_t 5668 emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5669 void *arg1) 5670 { 5671 uint32_t rval; 5672 5673 if (evt != FCF_EVENT_FCFI_OFFLINE) { 5674 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5675 "fcfi_offline_evt_action:%d %s:%s arg=%p. " 5676 "Invalid event type. Terminated.", 5677 fcfp->fcf_index, 5678 emlxs_fcfi_state_xlate(fcfp->state), 5679 emlxs_fcf_event_xlate(evt), arg1); 5680 return (1); 5681 } 5682 5683 if ((fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) && 5684 !(fcfp->flag & EMLXS_FCFI_PAUSE_REQ)) { 5685 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5686 "fcfi_offline_evt_action:%d. Offline already requested. " 5687 "Terminated.", 5688 fcfp->fcf_index); 5689 return (1); 5690 } 5691 5692 switch (fcfp->state) { 5693 case FCFI_STATE_OFFLINE: 5694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5695 "fcfi_offline_evt_action:%d flag=%x. Already offline. " 5696 "Terminated.", 5697 fcfp->fcf_index, 5698 fcfp->flag); 5699 break; 5700 5701 /* Wait states */ 5702 case FCFI_STATE_VFI_ONLINE: 5703 case FCFI_STATE_VFI_OFFLINE: 5704 case FCFI_STATE_REG: 5705 case FCFI_STATE_ONLINE: 5706 case FCFI_STATE_PAUSED: 5707 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5708 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5709 5710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5711 "fcfi_offline_evt_action:%d flag=%x. Handling offline.", 5712 fcfp->fcf_index, 5713 fcfp->flag); 5714 5715 /* Handle offline now */ 5716 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 5717 break; 5718 5719 /* Transitional states */ 5720 default: 5721 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5722 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5723 5724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5725 "fcfi_offline_evt_action:%d. " 5726 "Invalid state. Terminated.", 5727 fcfp->fcf_index); 5728 break; 5729 } 5730 5731 return (rval); 5732 5733 } /* emlxs_fcfi_offline_evt_action() */ 5734 5735 5736 /*ARGSUSED*/ 5737 static uint32_t 5738 emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5739 void *arg1) 5740 { 5741 uint32_t rval; 5742 5743 if (evt != FCF_EVENT_FCFI_PAUSE) { 5744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5745 "fcfi_pause_evt_action:%d %s:%s arg=%p. " 5746 "Invalid event type. Terminated.", 5747 fcfp->fcf_index, 5748 emlxs_fcfi_state_xlate(fcfp->state), 5749 emlxs_fcf_event_xlate(evt), arg1); 5750 return (1); 5751 } 5752 5753 if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { 5754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5755 "fcfi_pause_evt_action:%d. Pause already requested. " 5756 "Terminated.", 5757 fcfp->fcf_index); 5758 return (1); 5759 } 5760 5761 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { 5762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5763 "fcfi_pause_evt_action:%d. Offline already requested. " 5764 "Terminated.", 5765 fcfp->fcf_index); 5766 return (1); 5767 } 5768 5769 switch (fcfp->state) { 5770 case FCFI_STATE_OFFLINE: 5771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5772 "fcfi_pause_evt_action:%d flag=%x. Already offline. " 5773 "Terminated.", 5774 fcfp->fcf_index, 5775 fcfp->flag); 5776 break; 5777 5778 case FCFI_STATE_PAUSED: 5779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5780 "fcfi_pause_evt_action:%d flag=%x. Already paused. " 5781 "Terminated.", 5782 fcfp->fcf_index, 5783 fcfp->flag); 5784 break; 5785 5786 /* Wait states */ 5787 case FCFI_STATE_VFI_ONLINE: 5788 case FCFI_STATE_VFI_OFFLINE: 5789 case FCFI_STATE_REG: 5790 case FCFI_STATE_ONLINE: 5791 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5792 fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); 5793 5794 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5795 "fcfi_pause_evt_action:%d flag=%x. Handle pause request.", 5796 fcfp->fcf_index, 5797 fcfp->flag); 5798 5799 /* Handle offline now */ 5800 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 5801 break; 5802 5803 /* Transitional states */ 5804 default: 5805 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5806 fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); 5807 5808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5809 "fcfi_pause_evt_action:%d. " 5810 "Invalid state. Terminated.", 5811 fcfp->fcf_index); 5812 break; 5813 } 5814 5815 return (rval); 5816 5817 } /* emlxs_fcfi_pause_evt_action() */ 5818 5819 5820 /*ARGSUSED*/ 5821 static uint32_t 5822 emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, 5823 uint32_t evt, void *arg1) 5824 { 5825 uint32_t rval; 5826 5827 fcfp->attempts++; 5828 5829 if (fcfp->state != FCFI_STATE_UNREG_FAILED) { 5830 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5831 "fcfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " 5832 "Invalid state. Terminated.", 5833 fcfp->fcf_index, 5834 emlxs_fcfi_state_xlate(fcfp->state), 5835 emlxs_fcf_event_xlate(evt), 5836 arg1, fcfp->attempts); 5837 5838 return (1); 5839 } 5840 5841 if ((fcfp->reason == FCF_REASON_SEND_FAILED) || 5842 (fcfp->attempts >= 3)) { 5843 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5844 "fcfi_unreg_failed_action:%d attempt=%d reason=%x. " 5845 "Unreg cmpl.", 5846 fcfp->fcf_index, 5847 fcfp->attempts, 5848 fcfp->reason); 5849 5850 fcfp->flag &= ~EMLXS_FCFI_REG; 5851 5852 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL, 5853 FCF_REASON_OP_FAILED, fcfp->attempts, arg1); 5854 } else { 5855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5856 "fcfi_unreg_failed_action:%d attempt=%d. Unregistering.", 5857 fcfp->fcf_index, 5858 arg1, fcfp->attempts); 5859 5860 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, 5861 FCF_REASON_OP_FAILED, fcfp->attempts, arg1); 5862 } 5863 5864 return (rval); 5865 5866 } /* emlxs_fcfi_unreg_failed_action() */ 5867 5868 5869 /*ARGSUSED*/ 5870 static uint32_t 5871 emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5872 void *arg1) 5873 { 5874 uint32_t rval; 5875 5876 fcfp->attempts++; 5877 5878 if (fcfp->state != FCFI_STATE_REG_FAILED) { 5879 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5880 "fcfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " 5881 "Invalid state. Terminated.", 5882 fcfp->fcf_index, 5883 emlxs_fcfi_state_xlate(fcfp->state), 5884 emlxs_fcf_event_xlate(evt), arg1, 5885 fcfp->attempts); 5886 5887 return (1); 5888 } 5889 5890 if ((fcfp->reason == FCF_REASON_SEND_FAILED) || 5891 (fcfp->attempts >= 3)) { 5892 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5893 "fcfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", 5894 fcfp->fcf_index, 5895 fcfp->attempts, 5896 fcfp->reason); 5897 5898 fcfp->flag &= ~EMLXS_FCFI_REG; 5899 fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; 5900 fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; 5901 5902 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL, 5903 FCF_REASON_OP_FAILED, fcfp->attempts, arg1); 5904 } else { 5905 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5906 "fcfi_reg_failed_action:%d attempt=%d. Registering.", 5907 fcfp->fcf_index, 5908 fcfp->attempts); 5909 5910 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, 5911 FCF_REASON_OP_FAILED, fcfp->attempts, arg1); 5912 } 5913 5914 return (rval); 5915 5916 } /* emlxs_fcfi_reg_failed_action() */ 5917 5918 5919 /*ARGSUSED*/ 5920 static uint32_t 5921 emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 5922 { 5923 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 5924 MAILBOX4 *mb4; 5925 FCFIobj_t *fcfp; 5926 5927 fcfp = (FCFIobj_t *)mbq->context; 5928 mb4 = (MAILBOX4 *)mbq; 5929 5930 mutex_enter(&EMLXS_FCF_LOCK); 5931 5932 if (fcfp->state != FCFI_STATE_REG) { 5933 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5934 "fcfi_reg_mbcmpl:%d state=%s. Terminated.", 5935 fcfp->fcf_index, 5936 emlxs_fcfi_state_xlate(fcfp->state)); 5937 5938 mutex_exit(&EMLXS_FCF_LOCK); 5939 return (0); 5940 } 5941 5942 if (mb4->mbxStatus) { 5943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5944 "fcfi_reg_mbcmpl:%d failed. status=%x", 5945 fcfp->fcf_index, 5946 mb4->mbxStatus); 5947 5948 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, 5949 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 5950 5951 mutex_exit(&EMLXS_FCF_LOCK); 5952 return (0); 5953 } 5954 5955 fcfp->FCFI = mb4->un.varRegFCFI.FCFI; 5956 5957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 5958 "fcfi_reg_mbcmpl:%d Registered. FCFI=%d", 5959 fcfp->fcf_index, 5960 fcfp->FCFI); 5961 5962 fcfp->flag |= EMLXS_FCFI_REG; 5963 5964 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL, 5965 0, 0, 0); 5966 mutex_exit(&EMLXS_FCF_LOCK); 5967 return (0); 5968 5969 } /* emlxs_fcfi_reg_mbcmpl() */ 5970 5971 5972 /*ARGSUSED*/ 5973 static uint32_t 5974 emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 5975 void *arg1) 5976 { 5977 emlxs_hba_t *hba = HBA; 5978 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 5979 MAILBOX4 *mb4; 5980 MAILBOXQ *mbq; 5981 uint32_t rval; 5982 5983 if (fcfp->state != FCFI_STATE_REG) { 5984 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 5985 "fcfi_reg_action:%d %s:%s arg=%p. " 5986 "Invalid state. Terminated.", 5987 fcfp->fcf_index, 5988 emlxs_fcfi_state_xlate(fcfp->state), 5989 emlxs_fcf_event_xlate(evt), arg1); 5990 return (1); 5991 } 5992 5993 if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) { 5994 fcfp->flag |= EMLXS_FCFI_FCFTAB; 5995 fcftab->fcfi_online++; 5996 } 5997 5998 if (fcfp->prev_state != FCFI_STATE_REG_FAILED) { 5999 fcfp->attempts = 0; 6000 } 6001 6002 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { 6003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6004 "fcfi_reg_action:%d attempts=%d. Offline requested.", 6005 fcfp->fcf_index, 6006 fcfp->attempts); 6007 6008 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 6009 return (rval); 6010 } 6011 6012 if (fcfp->flag & EMLXS_FCFI_REG) { 6013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6014 "fcfi_reg_action:%d. Already registered. Skipping reg.", 6015 fcfp->fcf_index); 6016 6017 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, 6018 FCF_REASON_EVENT, evt, arg1); 6019 return (rval); 6020 } 6021 6022 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6023 "fcfi_reg_action:%d attempts=%d. Sending FCFI_REG.", 6024 fcfp->fcf_index, 6025 fcfp->attempts); 6026 6027 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 6028 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, 6029 FCF_REASON_NO_MBOX, 0, arg1); 6030 6031 return (rval); 6032 } 6033 mb4 = (MAILBOX4*)mbq; 6034 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 6035 6036 mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl; 6037 mbq->context = (void *)fcfp; 6038 mbq->port = (void *)port; 6039 6040 mb4->mbxCommand = MBX_REG_FCFI; 6041 mb4->mbxOwner = OWN_HOST; 6042 mb4->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */ 6043 mb4->un.varRegFCFI.InfoIndex = fcfp->fcf_index; 6044 6045 mb4->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid; 6046 mb4->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK; 6047 mb4->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL; 6048 mb4->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK; 6049 mb4->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE; 6050 6051 mb4->un.varRegFCFI.RQId1 = 0xffff; 6052 mb4->un.varRegFCFI.RQId2 = 0xffff; 6053 mb4->un.varRegFCFI.RQId3 = 0xffff; 6054 6055 if (fcfp->flag & EMLXS_FCFI_VLAN_ID) { 6056 mb4->un.varRegFCFI.vv = 1; 6057 mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id; 6058 } 6059 6060 /* Ignore the fcf record and force FPMA */ 6061 mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA; 6062 6063 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 6064 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 6065 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6066 6067 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, 6068 FCF_REASON_SEND_FAILED, rval, arg1); 6069 6070 return (rval); 6071 } 6072 6073 return (0); 6074 6075 } /* emlxs_fcfi_reg_action() */ 6076 6077 6078 /*ARGSUSED*/ 6079 static uint32_t 6080 emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 6081 void *arg1) 6082 { 6083 uint32_t rval; 6084 6085 if (fcfp->state != FCFI_STATE_REG_CMPL) { 6086 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6087 "fcfi_reg_cmpl_action:%d %s:%s arg=%p. " 6088 "Invalid state. Terminated.", 6089 fcfp->fcf_index, 6090 emlxs_fcfi_state_xlate(fcfp->state), 6091 emlxs_fcf_event_xlate(evt), arg1); 6092 return (1); 6093 } 6094 6095 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { 6096 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6097 "fcfi_reg_cmpl_action:%d. Offline requested.", 6098 fcfp->fcf_index); 6099 6100 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 6101 return (rval); 6102 } 6103 6104 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6105 "fcfi_reg_cmpl_action:%d attempts=%d. Reg cmpl.", 6106 fcfp->fcf_index, 6107 fcfp->attempts); 6108 6109 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, 6110 FCF_REASON_EVENT, evt, arg1); 6111 6112 return (rval); 6113 6114 } /* emlxs_fcfi_reg_cmpl_action() */ 6115 6116 6117 /*ARGSUSED*/ 6118 static uint32_t 6119 emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 6120 { 6121 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 6122 MAILBOX4 *mb4; 6123 FCFIobj_t *fcfp; 6124 6125 fcfp = (FCFIobj_t *)mbq->context; 6126 mb4 = (MAILBOX4 *)mbq; 6127 6128 mutex_enter(&EMLXS_FCF_LOCK); 6129 6130 if (fcfp->state != FCFI_STATE_UNREG) { 6131 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6132 "fcfi_unreg_mbcmpl:%d state=%s. Terminated.", 6133 fcfp->fcf_index, 6134 emlxs_fcfi_state_xlate(fcfp->state)); 6135 6136 mutex_exit(&EMLXS_FCF_LOCK); 6137 return (0); 6138 } 6139 6140 if (mb4->mbxStatus) { 6141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6142 "fcfi_unreg_mbcmpl:%d failed. status=%x", 6143 fcfp->fcf_index, 6144 mb4->mbxStatus); 6145 6146 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, 6147 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 6148 6149 mutex_exit(&EMLXS_FCF_LOCK); 6150 return (0); 6151 } 6152 6153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6154 "fcfi_unreg_mbcmpl:%d Unregistered.", 6155 fcfp->fcf_index); 6156 6157 fcfp->flag &= ~EMLXS_FCFI_REG; 6158 (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL, 6159 0, 0, 0); 6160 6161 mutex_exit(&EMLXS_FCF_LOCK); 6162 return (0); 6163 6164 } /* emlxs_fcfi_unreg_mbcmpl() */ 6165 6166 6167 /*ARGSUSED*/ 6168 static uint32_t 6169 emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 6170 void *arg1) 6171 { 6172 emlxs_hba_t *hba = HBA; 6173 MAILBOX4 *mb4; 6174 MAILBOXQ *mbq; 6175 uint32_t rval; 6176 6177 if (fcfp->state != FCFI_STATE_UNREG) { 6178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6179 "fcfi_unreg_action:%d %s:%s arg=%p. " 6180 "Invalid state. Terminated.", 6181 fcfp->fcf_index, 6182 emlxs_fcfi_state_xlate(fcfp->state), 6183 emlxs_fcf_event_xlate(evt), arg1); 6184 6185 return (1); 6186 } 6187 6188 if (!(fcfp->flag & EMLXS_FCFI_REG)) { 6189 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6190 "fcfi_unreg_action:%d. Not registered. Skipping unreg.", 6191 fcfp->fcf_index); 6192 6193 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, 6194 FCF_REASON_EVENT, evt, arg1); 6195 return (rval); 6196 } 6197 6198 if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) { 6199 fcfp->attempts = 0; 6200 } 6201 6202 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6203 "fcfi_unreg_action:%d attempts=%d. Sending FCFI_UNREG.", 6204 fcfp->fcf_index, 6205 fcfp->attempts); 6206 6207 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 6208 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, 6209 FCF_REASON_NO_MBOX, 0, arg1); 6210 return (rval); 6211 } 6212 mb4 = (MAILBOX4*)mbq; 6213 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 6214 6215 mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl; 6216 mbq->context = (void *)fcfp; 6217 mbq->port = (void *)port; 6218 6219 mb4->mbxCommand = MBX_UNREG_FCFI; 6220 mb4->mbxOwner = OWN_HOST; 6221 mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI; 6222 6223 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 6224 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 6225 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6226 6227 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, 6228 FCF_REASON_SEND_FAILED, rval, arg1); 6229 6230 return (rval); 6231 } 6232 6233 return (0); 6234 6235 } /* emlxs_fcfi_unreg_action() */ 6236 6237 6238 /*ARGSUSED*/ 6239 static uint32_t 6240 emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 6241 void *arg1) 6242 { 6243 uint32_t rval; 6244 6245 if (fcfp->state != FCFI_STATE_UNREG_CMPL) { 6246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6247 "fcfi_unreg_cmpl_action:%d %s:%s arg=%p. " 6248 "Invalid state. Terminated.", 6249 fcfp->fcf_index, 6250 emlxs_fcfi_state_xlate(fcfp->state), 6251 emlxs_fcf_event_xlate(evt), arg1); 6252 return (1); 6253 } 6254 6255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6256 "fcfi_unreg_cmpl_action:%d attempts=%d. Going offline.", 6257 fcfp->fcf_index, 6258 emlxs_fcfi_state_xlate(fcfp->state), 6259 emlxs_fcf_event_xlate(evt), arg1, 6260 fcfp->attempts); 6261 6262 rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, 6263 FCF_REASON_EVENT, evt, arg1); 6264 6265 return (rval); 6266 6267 } /* emlxs_fcfi_unreg_cmpl_action() */ 6268 6269 6270 /*ARGSUSED*/ 6271 static uint32_t 6272 emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, 6273 void *arg1) 6274 { 6275 emlxs_hba_t *hba = HBA; 6276 uint32_t rval; 6277 VFIobj_t *vfip; 6278 uint32_t i; 6279 6280 if (fcfp->state != FCFI_STATE_ONLINE) { 6281 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6282 "fcfi_online_action:%d %s:%s arg=%p. " 6283 "Invalid state. Terminated.", 6284 fcfp->fcf_index, 6285 emlxs_fcfi_state_xlate(fcfp->state), 6286 emlxs_fcf_event_xlate(evt), arg1); 6287 return (1); 6288 } 6289 6290 fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ; 6291 6292 if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { 6293 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6294 "fcfi_online_action:%d attempts=%d. Offline requested.", 6295 fcfp->fcf_index, 6296 fcfp->attempts); 6297 6298 rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); 6299 return (1); 6300 } 6301 6302 /* Online remaining VFI's for this FCFI */ 6303 vfip = hba->sli.sli4.VFI_table; 6304 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { 6305 if (vfip->fcfp != fcfp) { 6306 continue; 6307 } 6308 6309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6310 "fcfi_online_action:%d vfi_online=%d. Onlining VFI:%d.", 6311 fcfp->fcf_index, 6312 fcfp->vfi_online, 6313 vfip->VFI); 6314 6315 (void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); 6316 } 6317 6318 if (fcfp->prev_state != FCFI_STATE_ONLINE) { 6319 /* Perform VSAN discovery check when first VFI goes online */ 6320 if (fcfp->vfi_online < FCFI_MAX_VFI_COUNT) { 6321 6322 /* Perform VSAN Discovery (TBD) */ 6323 /* For now we only need 1 VFI */ 6324 6325 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6326 "fcfi_online_action:%d vfi_online=%d. " 6327 "VSAN discovery required.", 6328 fcfp->fcf_index, 6329 fcfp->vfi_online); 6330 } 6331 } 6332 6333 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6334 "fcfi_online_action:%d vfi_online=%d. " 6335 "FCFI online. Notifying fcftab.", 6336 fcfp->fcf_index, 6337 fcfp->vfi_online); 6338 6339 /* Notify FCFTAB */ 6340 rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp); 6341 6342 return (rval); 6343 6344 } /* emlxs_fcfi_online_action() */ 6345 6346 6347 /*ARGSUSED*/ 6348 static int 6349 emlxs_fcf_configured(emlxs_port_t *port, FCFIobj_t *fcfp) 6350 { 6351 emlxs_hba_t *hba = HBA; 6352 int i; 6353 uint32_t entry_count; 6354 uint32_t valid_entry; 6355 uint32_t match_found; 6356 uint16_t VLanId; 6357 FCF_RECORD_t *fcfrec = &fcfp->fcf_rec; 6358 uint32_t j; 6359 uint32_t k; 6360 6361 /* Init the primary flag, we may set it later */ 6362 fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT); 6363 6364 if (!(hba->flag & FC_FIP_SUPPORTED)) { 6365 if (!hba->sli.sli4.cfgFCOE.length) { 6366 /* Nothing specified, so everything matches */ 6367 /* For nonFIP only use index 0 */ 6368 if (fcfrec->fcf_index == 0) { 6369 return (1); /* success */ 6370 } 6371 return (0); 6372 } 6373 6374 /* Just check FCMap for now */ 6375 if (bcmp((char *)fcfrec->fc_map, 6376 hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) { 6377 return (1); /* success */ 6378 } 6379 return (0); 6380 } 6381 6382 /* For FIP mode, the FCF record must match Config Region 23 */ 6383 6384 entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) / 6385 sizeof (tlv_fcfconnectentry_t); 6386 valid_entry = 0; 6387 match_found = 0; 6388 6389 for (i = 0; i < entry_count; i++) { 6390 6391 if (!hba->sli.sli4.cfgFCF.entry[i].Valid) { 6392 continue; 6393 } 6394 6395 if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) { 6396 valid_entry = 1; 6397 6398 if (bcmp((char *)fcfrec->fabric_name_identifier, 6399 hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) { 6400 match_found = 0; 6401 continue; 6402 } 6403 6404 match_found = 1; 6405 } 6406 6407 if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) { 6408 valid_entry = 1; 6409 6410 if (bcmp((char *)fcfrec->switch_name_identifier, 6411 hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) { 6412 match_found = 0; 6413 continue; 6414 } 6415 6416 match_found = 1; 6417 } 6418 6419 if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) { 6420 valid_entry = 1; 6421 6422 if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) { 6423 match_found = 0; 6424 continue; 6425 } 6426 6427 VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId; 6428 j = VLanId / 8; 6429 k = 1 << (VLanId % 8); 6430 6431 if (!(fcfrec->vlan_bitmap[j] & k)) { 6432 match_found = 0; 6433 continue; 6434 } 6435 6436 /* Assign requested vlan_id to this FCF */ 6437 fcfp->vlan_id = VLanId; 6438 6439 match_found = 1; 6440 } 6441 6442 /* If a match was found */ 6443 if (match_found) { 6444 if (hba->sli.sli4.cfgFCF.entry[i].Primary) { 6445 fcfp->flag |= EMLXS_FCFI_PRIMARY; 6446 } 6447 if (hba->sli.sli4.cfgFCF.entry[i].Boot) { 6448 fcfp->flag |= EMLXS_FCFI_BOOT; 6449 } 6450 return (1); 6451 } 6452 } 6453 6454 /* If no valid entries found, then allow any fabric */ 6455 if (!valid_entry) { 6456 return (1); 6457 } 6458 6459 return (0); 6460 6461 } /* emlxs_fcf_configured() */ 6462 6463 6464 static void 6465 emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec, 6466 uint32_t event_tag) 6467 { 6468 emlxs_hba_t *hba = HBA; 6469 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 6470 uint16_t i; 6471 6472 bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t)); 6473 fcfp->fcf_index = fcf_rec->fcf_index; 6474 6475 /* Clear VLAN info */ 6476 fcfp->vlan_id = 0; 6477 fcfp->flag &= ~EMLXS_FCFI_VLAN_ID; 6478 6479 /* Check if fcf is a member of a VLAN */ 6480 for (i = 0; i < 4096; i++) { 6481 if (fcf_rec->vlan_bitmap[i / 8] & (1 << (i % 8))) { 6482 /* For now assign the VLAN id of the first VLAN found */ 6483 fcfp->vlan_id = i; 6484 fcfp->flag |= EMLXS_FCFI_VLAN_ID; 6485 break; 6486 } 6487 } 6488 6489 if (fcf_rec->fcf_available) { 6490 fcfp->flag |= EMLXS_FCFI_AVAILABLE; 6491 } else { 6492 fcfp->flag &= ~EMLXS_FCFI_AVAILABLE; 6493 } 6494 6495 if (fcf_rec->fcf_valid) { 6496 fcfp->flag |= EMLXS_FCFI_VALID; 6497 } else { 6498 fcfp->flag &= ~EMLXS_FCFI_VALID; 6499 } 6500 6501 /* Check config region 23 */ 6502 /* Also sets BOOT and PRIMARY cfg bits as needed */ 6503 if (emlxs_fcf_configured(port, fcfp)) { 6504 fcfp->flag |= EMLXS_FCFI_CONFIGURED; 6505 } else { 6506 fcfp->flag &= ~EMLXS_FCFI_CONFIGURED; 6507 } 6508 6509 /* Set fcfp priority. Used by selection alogithm */ 6510 /* Combination of BOOT:PRIMARY:~fip_priority */ 6511 fcfp->priority = (fcfp->flag & EMLXS_FCFI_BOOT)? 0x200:0; 6512 fcfp->priority |= (fcfp->flag & EMLXS_FCFI_PRIMARY)? 0x100:0; 6513 fcfp->priority |= ~(fcf_rec->fip_priority & 0xff); 6514 6515 fcfp->event_tag = event_tag; 6516 fcfp->generation = fcftab->generation; 6517 fcfp->flag |= EMLXS_FCFI_FRESH; 6518 6519 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6520 "fcfi:%d gen=%x tag=%x flag=%x avl=%x val=%x state=%x " 6521 "map=%x pri=%x vid=%x", 6522 fcf_rec->fcf_index, 6523 fcfp->generation, 6524 fcfp->event_tag, 6525 fcfp->flag, 6526 fcf_rec->fcf_available, 6527 fcf_rec->fcf_valid, 6528 fcf_rec->fcf_state, 6529 fcf_rec->mac_address_provider, 6530 fcfp->priority, 6531 fcfp->vlan_id); 6532 6533 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6534 "fcfi:%d mac=%02x:%02x:%02x:%02x:%02x:%02x " 6535 "fabric=%02x%02x%02x%02x%02x%02x%02x%02x " 6536 "switch=%02x%02x%02x%02x%02x%02x%02x%02x", 6537 fcfp->fcf_index, 6538 fcf_rec->fcf_mac_address_hi[0], 6539 fcf_rec->fcf_mac_address_hi[1], 6540 fcf_rec->fcf_mac_address_hi[2], 6541 fcf_rec->fcf_mac_address_hi[3], 6542 fcf_rec->fcf_mac_address_low[0], 6543 fcf_rec->fcf_mac_address_low[1], 6544 6545 fcf_rec->fabric_name_identifier[0], 6546 fcf_rec->fabric_name_identifier[1], 6547 fcf_rec->fabric_name_identifier[2], 6548 fcf_rec->fabric_name_identifier[3], 6549 fcf_rec->fabric_name_identifier[4], 6550 fcf_rec->fabric_name_identifier[5], 6551 fcf_rec->fabric_name_identifier[6], 6552 fcf_rec->fabric_name_identifier[7], 6553 6554 fcf_rec->switch_name_identifier[0], 6555 fcf_rec->switch_name_identifier[1], 6556 fcf_rec->switch_name_identifier[2], 6557 fcf_rec->switch_name_identifier[3], 6558 fcf_rec->switch_name_identifier[4], 6559 fcf_rec->switch_name_identifier[5], 6560 fcf_rec->switch_name_identifier[6], 6561 fcf_rec->switch_name_identifier[7]); 6562 6563 return; 6564 6565 } /* emlxs_fcfi_update() */ 6566 6567 6568 /* ************************************************************************** */ 6569 /* VFI */ 6570 /* ************************************************************************** */ 6571 6572 static char * 6573 emlxs_vfi_state_xlate(uint32_t state) 6574 { 6575 static char buffer[32]; 6576 uint32_t i; 6577 uint32_t count; 6578 6579 count = sizeof (emlxs_vfi_state_table) / sizeof (emlxs_table_t); 6580 for (i = 0; i < count; i++) { 6581 if (state == emlxs_vfi_state_table[i].code) { 6582 return (emlxs_vfi_state_table[i].string); 6583 } 6584 } 6585 6586 (void) sprintf(buffer, "state=0x%x", state); 6587 return (buffer); 6588 6589 } /* emlxs_vfi_state_xlate() */ 6590 6591 6592 static uint32_t 6593 emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 6594 void *arg1) 6595 { 6596 uint32_t rval; 6597 uint32_t(*func) (emlxs_port_t *, VFIobj_t *, uint32_t, void *); 6598 uint32_t index; 6599 uint32_t events; 6600 uint16_t state; 6601 6602 /* Convert event to action table index */ 6603 switch (evt) { 6604 case FCF_EVENT_STATE_ENTER: 6605 index = 0; 6606 break; 6607 case FCF_EVENT_VFI_ONLINE: 6608 index = 1; 6609 break; 6610 case FCF_EVENT_VFI_OFFLINE: 6611 index = 2; 6612 break; 6613 case FCF_EVENT_VFI_PAUSE: 6614 index = 3; 6615 break; 6616 case FCF_EVENT_VPI_ONLINE: 6617 index = 4; 6618 break; 6619 case FCF_EVENT_VPI_OFFLINE: 6620 index = 5; 6621 break; 6622 default: 6623 return (1); 6624 } 6625 6626 events = VFI_ACTION_EVENTS; 6627 state = vfip->state; 6628 6629 index += (state * events); 6630 func = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *)) 6631 emlxs_vfi_action_table[index]; 6632 6633 if (!func) { 6634 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 6635 "vfi:%d %s:%s arg=%p. No action. Terminated.", 6636 vfip->VFI, 6637 emlxs_vfi_state_xlate(state), 6638 emlxs_fcf_event_xlate(evt), arg1); 6639 6640 return (1); 6641 } 6642 6643 rval = (func)(port, vfip, evt, arg1); 6644 6645 return (rval); 6646 6647 } /* emlxs_vfi_action() */ 6648 6649 6650 static uint32_t 6651 emlxs_vfi_event(emlxs_port_t *port, uint32_t evt, 6652 void *arg1) 6653 { 6654 VPIobj_t *vpip = NULL; 6655 VFIobj_t *vfip = NULL; 6656 uint32_t rval = 0; 6657 6658 /* Filter events and acquire fcfi context */ 6659 switch (evt) { 6660 case FCF_EVENT_VPI_ONLINE: 6661 case FCF_EVENT_VPI_OFFLINE: 6662 vpip = (VPIobj_t *)arg1; 6663 6664 if (!vpip) { 6665 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 6666 "vfi: %s arg=%p. Null VPI found. Terminated.", 6667 emlxs_fcf_event_xlate(evt), arg1); 6668 6669 return (1); 6670 } 6671 6672 vfip = vpip->vfip; 6673 6674 if (!vfip) { 6675 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 6676 "vfi: %s arg=%p. VFI not found. Terminated.", 6677 emlxs_fcf_event_xlate(evt), arg1); 6678 6679 return (1); 6680 } 6681 break; 6682 6683 case FCF_EVENT_VFI_ONLINE: 6684 case FCF_EVENT_VFI_OFFLINE: 6685 case FCF_EVENT_VFI_PAUSE: 6686 vfip = (VFIobj_t *)arg1; 6687 6688 if (!vfip) { 6689 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 6690 "vfi: %s arg=%p. VFI not found. Terminated.", 6691 emlxs_fcf_event_xlate(evt), arg1); 6692 6693 return (1); 6694 } 6695 break; 6696 6697 default: 6698 return (1); 6699 } 6700 6701 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 6702 "vfi:%d %s:%s arg=%p", 6703 vfip->VFI, 6704 emlxs_vfi_state_xlate(vfip->state), 6705 emlxs_fcf_event_xlate(evt), arg1); 6706 6707 rval = emlxs_vfi_action(port, vfip, evt, arg1); 6708 6709 return (rval); 6710 6711 } /* emlxs_vfi_event() */ 6712 6713 6714 /*ARGSUSED*/ 6715 static uint32_t 6716 emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state, 6717 uint16_t reason, uint32_t explain, void *arg1) 6718 { 6719 uint32_t rval; 6720 6721 if (state >= VFI_ACTION_STATES) { 6722 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6723 "vfi_state:%d %s. " 6724 "Invalid state. Terminated.", 6725 vfip->VFI, 6726 emlxs_vfi_state_xlate(vfip->state)); 6727 6728 return (1); 6729 } 6730 6731 if ((vfip->state == state) && 6732 (reason != FCF_REASON_REENTER)) { 6733 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6734 "vfi_state:%d %s:%s:0x%x arg=%p. " 6735 "State not changed. Terminated.", 6736 vfip->VFI, 6737 emlxs_vfi_state_xlate(vfip->state), 6738 emlxs_fcf_reason_xlate(reason), 6739 explain, arg1); 6740 6741 return (1); 6742 } 6743 6744 if (!reason) { 6745 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 6746 "vfi:%d %s-->%s arg=%p", 6747 vfip->VFI, 6748 emlxs_vfi_state_xlate(vfip->state), 6749 emlxs_vfi_state_xlate(state), arg1); 6750 } else if (reason == FCF_REASON_EVENT) { 6751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 6752 "vfi:%d %s-->%s:%s:%s arg=%p", 6753 vfip->VFI, 6754 emlxs_vfi_state_xlate(vfip->state), 6755 emlxs_vfi_state_xlate(state), 6756 emlxs_fcf_reason_xlate(reason), 6757 emlxs_fcf_event_xlate(explain), arg1); 6758 } else if (explain) { 6759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 6760 "vfi:%d %s-->%s:%s:0x%x arg=%p", 6761 vfip->VFI, 6762 emlxs_vfi_state_xlate(vfip->state), 6763 emlxs_vfi_state_xlate(state), 6764 emlxs_fcf_reason_xlate(reason), 6765 explain, arg1); 6766 } else { 6767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 6768 "vfi:%d %s-->%s:%s arg=%p", 6769 vfip->VFI, 6770 emlxs_vfi_state_xlate(vfip->state), 6771 emlxs_vfi_state_xlate(state), 6772 emlxs_fcf_reason_xlate(reason), arg1); 6773 } 6774 6775 vfip->prev_state = vfip->state; 6776 vfip->prev_reason = vfip->reason; 6777 vfip->state = state; 6778 vfip->reason = reason; 6779 6780 rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1); 6781 6782 return (rval); 6783 6784 } /* emlxs_vfi_state() */ 6785 6786 6787 /*ARGSUSED*/ 6788 static uint32_t 6789 emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, 6790 uint32_t evt, void *arg1) 6791 { 6792 uint32_t rval; 6793 6794 if (evt != FCF_EVENT_VPI_ONLINE) { 6795 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6796 "vfi_vpi_online_evt_action:%d %s:%s arg=%p flag=%x. " 6797 "Invalid event type. Terminated.", 6798 vfip->VFI, 6799 emlxs_vfi_state_xlate(vfip->state), 6800 emlxs_fcf_event_xlate(evt), arg1, 6801 vfip->flag); 6802 6803 return (1); 6804 } 6805 6806 switch (vfip->state) { 6807 case VFI_STATE_ONLINE: 6808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6809 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " 6810 "Reentering online.", 6811 vfip->VFI, 6812 vfip->flag, 6813 vfip->vpi_online); 6814 6815 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, 6816 FCF_REASON_REENTER, evt, arg1); 6817 break; 6818 6819 case VFI_STATE_VPI_ONLINE: 6820 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6821 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " 6822 "Online cmpl.", 6823 vfip->VFI, 6824 vfip->flag, 6825 vfip->vpi_online); 6826 6827 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL, 6828 FCF_REASON_EVENT, evt, arg1); 6829 break; 6830 6831 default: 6832 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6833 "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " 6834 "Terminated.", 6835 vfip->VFI, 6836 vfip->flag, 6837 vfip->vpi_online); 6838 6839 return (1); 6840 } 6841 6842 return (rval); 6843 6844 } /* emlxs_vfi_vpi_online_evt_action() */ 6845 6846 6847 /*ARGSUSED*/ 6848 static uint32_t 6849 emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1) 6850 { 6851 uint32_t rval; 6852 6853 if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { 6854 return (0); 6855 } 6856 6857 if (vfip->vpi_online > 0) { 6858 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { 6859 rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED, 6860 FCF_REASON_REQUESTED, 0, arg1); 6861 } else { 6862 rval = emlxs_vfi_state(port, vfip, 6863 VFI_STATE_VPI_OFFLINE, FCF_REASON_REQUESTED, 6864 0, arg1); 6865 } 6866 6867 } else if (vfip->flag & EMLXS_VFI_REG) { 6868 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, 6869 FCF_REASON_REQUESTED, 0, arg1); 6870 6871 } else if (vfip->flag & EMLXS_VFI_INIT) { 6872 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, 6873 FCF_REASON_REQUESTED, 0, arg1); 6874 6875 } else { 6876 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, 6877 FCF_REASON_REQUESTED, 0, arg1); 6878 } 6879 6880 return (rval); 6881 6882 } /* emlxs_vfi_offline_handler() */ 6883 6884 6885 /*ARGSUSED*/ 6886 static uint32_t 6887 emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, 6888 uint32_t evt, void *arg1) 6889 { 6890 uint32_t rval; 6891 VPIobj_t *vpip; 6892 6893 if (evt != FCF_EVENT_VPI_OFFLINE) { 6894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6895 "vfi_vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " 6896 "Invalid event type. Terminated.", 6897 vfip->VFI, 6898 emlxs_vfi_state_xlate(vfip->state), 6899 emlxs_fcf_event_xlate(evt), arg1, 6900 vfip->flag); 6901 return (1); 6902 } 6903 6904 /* Disconnect VPI object from VFI */ 6905 vpip = (VPIobj_t *)arg1; 6906 vpip->vfip = NULL; 6907 6908 switch (vfip->state) { 6909 case VFI_STATE_ONLINE: 6910 case VFI_STATE_VPI_ONLINE: 6911 if (vfip->vpi_online == 0) { 6912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6913 "vfi_vpi_offline_evt_action:%d flag=%x " 6914 "vpi_online=%d. Offlining.", 6915 vfip->VFI, 6916 vfip->flag, vfip->vpi_online); 6917 6918 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 6919 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 6920 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 6921 } else { 6922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6923 "vfi_vpi_offline_evt_action:%d flag=%x " 6924 "vpi_online=%d. Terminated.", 6925 vfip->VFI, 6926 vfip->flag, vfip->vpi_online); 6927 } 6928 break; 6929 6930 case VFI_STATE_PAUSED: 6931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6932 "vfi_vpi_offline_evt_action:%d flag=%x vpi_online=%d. " 6933 "Terminated.", 6934 vfip->VFI, 6935 vfip->flag, vfip->vpi_online); 6936 break; 6937 6938 case VFI_STATE_VPI_OFFLINE: 6939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6940 "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.", 6941 vfip->VFI, 6942 vfip->flag); 6943 6944 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL, 6945 FCF_REASON_EVENT, evt, arg1); 6946 break; 6947 6948 case VFI_STATE_VPI_OFFLINE_CMPL: 6949 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6950 "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.", 6951 vfip->VFI, 6952 vfip->flag); 6953 6954 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL, 6955 FCF_REASON_REENTER, evt, arg1); 6956 break; 6957 6958 default: 6959 if (vfip->vpi_online == 0) { 6960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6961 "vfi_vpi_offline_evt_action:%d flag=%x "\ 6962 "vpi_online=%d. Requesting offline.", 6963 vfip->VFI, 6964 vfip->flag, vfip->vpi_online); 6965 6966 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 6967 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 6968 } else { 6969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 6970 "vfi_vpi_offline_evt_action:%d flag=%x "\ 6971 "vpi_online=%d. Terminated.", 6972 vfip->VFI, 6973 vfip->flag, vfip->vpi_online); 6974 } 6975 return (1); 6976 } 6977 6978 return (rval); 6979 6980 } /* emlxs_vfi_vpi_offline_evt_action() */ 6981 6982 6983 /*ARGSUSED*/ 6984 static uint32_t 6985 emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 6986 void *arg1) 6987 { 6988 emlxs_hba_t *hba = HBA; 6989 emlxs_port_t *vport; 6990 VPIobj_t *vpip; 6991 uint32_t rval = 0; 6992 uint32_t i; 6993 6994 if (evt != FCF_EVENT_VFI_ONLINE) { 6995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 6996 "vfi_online_evt_action:%d %s:%s arg=%p flag=%x. " 6997 "Invalid event type. Terminated.", 6998 vfip->VFI, 6999 emlxs_vfi_state_xlate(vfip->state), 7000 emlxs_fcf_event_xlate(evt), arg1, 7001 vfip->flag); 7002 return (1); 7003 } 7004 7005 if (vfip->flag & EMLXS_VFI_ONLINE_REQ) { 7006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7007 "vfi_online_evt_action:%d flag=%x. " 7008 "Online already requested. Terminated.", 7009 vfip->VFI, 7010 vfip->flag); 7011 return (0); 7012 } 7013 7014 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7015 vfip->flag |= EMLXS_VFI_ONLINE_REQ; 7016 7017 switch (vfip->state) { 7018 case VFI_STATE_OFFLINE: 7019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7020 "vfi_online_evt_action:%d flag=%x. Initiating online.", 7021 vfip->VFI, 7022 vfip->flag); 7023 7024 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, 7025 FCF_REASON_EVENT, evt, arg1); 7026 break; 7027 7028 case VFI_STATE_VPI_OFFLINE: 7029 case VFI_STATE_PAUSED: 7030 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7031 "vfi_online_evt_action:%d flag=%x. Initiating online.", 7032 vfip->VFI, 7033 vfip->flag); 7034 7035 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, 7036 FCF_REASON_EVENT, evt, arg1); 7037 break; 7038 7039 case VFI_STATE_ONLINE: 7040 /* Online all VPI's belonging to this vfi */ 7041 for (i = 0; i <= hba->vpi_max; i++) { 7042 vport = &VPORT(i); 7043 vpip = &vport->VPIobj; 7044 7045 if (!(vport->flag & EMLXS_PORT_BOUND)) { 7046 continue; 7047 } 7048 7049 if (vpip->vfip != vfip) { 7050 continue; 7051 } 7052 7053 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7054 "vfi_online_evt_action:%d. Onlining VPI:%d", 7055 vfip->VFI, 7056 vpip->VPI); 7057 7058 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, 7059 vpip); 7060 } 7061 break; 7062 7063 default: 7064 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7065 "vfi_online_evt_action:%d flag=%x. Terminated.", 7066 vfip->VFI, 7067 vfip->flag); 7068 return (1); 7069 } 7070 7071 return (rval); 7072 7073 } /* emlxs_vfi_online_evt_action() */ 7074 7075 7076 /*ARGSUSED*/ 7077 static uint32_t 7078 emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7079 void *arg1) 7080 { 7081 uint32_t rval = 0; 7082 7083 if (evt != FCF_EVENT_VFI_OFFLINE) { 7084 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7085 "vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. " 7086 "Invalid event type. Terminated.", 7087 vfip->VFI, 7088 emlxs_vfi_state_xlate(vfip->state), 7089 emlxs_fcf_event_xlate(evt), arg1, 7090 vfip->flag); 7091 return (1); 7092 } 7093 7094 if ((vfip->flag & EMLXS_VFI_OFFLINE_REQ) && 7095 !(vfip->flag & EMLXS_VFI_PAUSE_REQ)) { 7096 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7097 "vfi_offline_evt_action:%d flag=%x. " 7098 "Offline already requested. Terminated.", 7099 vfip->VFI, 7100 vfip->flag); 7101 return (0); 7102 } 7103 7104 switch (vfip->state) { 7105 case VFI_STATE_OFFLINE: 7106 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7107 "vfi_offline_evt_action:%d flag=%x. " 7108 "Already offline. Terminated.", 7109 vfip->VFI, 7110 vfip->flag); 7111 break; 7112 7113 /* Wait states */ 7114 case VFI_STATE_VPI_ONLINE: 7115 case VFI_STATE_VPI_OFFLINE: 7116 case VFI_STATE_VPI_OFFLINE_CMPL: 7117 case VFI_STATE_INIT: 7118 case VFI_STATE_REG: 7119 case VFI_STATE_ONLINE: 7120 case VFI_STATE_PAUSED: 7121 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7122 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 7123 7124 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7125 "vfi_offline_evt_action:%d flag=%x. Handling offline.", 7126 vfip->VFI, 7127 vfip->flag); 7128 7129 /* Handle offline now */ 7130 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 7131 break; 7132 7133 default: 7134 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7135 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 7136 7137 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7138 "vfi_offline_evt_action:%d flag=%x. Terminated.", 7139 vfip->VFI, 7140 vfip->flag); 7141 break; 7142 } 7143 7144 return (rval); 7145 7146 } /* emlxs_vfi_offline_evt_action() */ 7147 7148 7149 /*ARGSUSED*/ 7150 static uint32_t 7151 emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7152 void *arg1) 7153 { 7154 uint32_t rval = 0; 7155 7156 if (evt != FCF_EVENT_VFI_PAUSE) { 7157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7158 "vfi_pause_evt_action:%d %s:%s arg=%p flag=%x. " 7159 "Invalid event type. Terminated.", 7160 vfip->VFI, 7161 emlxs_vfi_state_xlate(vfip->state), 7162 emlxs_fcf_event_xlate(evt), arg1, 7163 vfip->flag); 7164 return (1); 7165 } 7166 7167 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { 7168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7169 "vfi_pause_evt_action:%d flag=%x. " 7170 "Pause already requested. Terminated.", 7171 vfip->VFI, 7172 vfip->flag); 7173 return (0); 7174 } 7175 7176 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 7177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7178 "vfi_pause_evt_action:%d flag=%x. " 7179 "Offline already requested. Terminated.", 7180 vfip->VFI, 7181 vfip->flag); 7182 return (0); 7183 } 7184 7185 switch (vfip->state) { 7186 case VFI_STATE_OFFLINE: 7187 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7188 "vfi_pause_evt_action:%d flag=%x. " 7189 "Already offline. Terminated.", 7190 vfip->VFI, 7191 vfip->flag); 7192 break; 7193 7194 case VFI_STATE_PAUSED: 7195 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7196 "vfi_pause_evt_action:%d flag=%x. " 7197 "Already paused. Terminated.", 7198 vfip->VFI, 7199 vfip->flag); 7200 break; 7201 7202 /* Wait states */ 7203 case VFI_STATE_VPI_ONLINE: 7204 case VFI_STATE_VPI_OFFLINE_CMPL: 7205 case VFI_STATE_INIT: 7206 case VFI_STATE_REG: 7207 case VFI_STATE_ONLINE: 7208 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7209 vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); 7210 7211 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7212 "vfi_pause_evt_action:%d flag=%x. Handling offline.", 7213 vfip->VFI, 7214 vfip->flag); 7215 7216 /* Handle offline now */ 7217 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 7218 break; 7219 7220 default: 7221 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7222 vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); 7223 7224 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7225 "vfi_pause_evt_action:%d flag=%x. Terminated.", 7226 vfip->VFI, 7227 vfip->flag); 7228 break; 7229 } 7230 7231 return (rval); 7232 7233 } /* emlxs_vfi_pause_evt_action() */ 7234 7235 7236 /*ARGSUSED*/ 7237 static uint32_t 7238 emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7239 void *arg1) 7240 { 7241 uint32_t rval; 7242 7243 if (vfip->state != VFI_STATE_OFFLINE) { 7244 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7245 "vfi_offline_action:%d %s:%s arg=%p. " 7246 "Invalid state. Terminated.", 7247 vfip->VFI, 7248 emlxs_vfi_state_xlate(vfip->state), 7249 emlxs_fcf_event_xlate(evt), arg1); 7250 return (1); 7251 } 7252 7253 if (!vfip->fcfp) { 7254 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7255 "vfi_offline_action:%d %s:%s arg=%p flag=%x. " 7256 "Null fcfp found. Terminated.", 7257 vfip->VFI, 7258 emlxs_vfi_state_xlate(vfip->state), 7259 emlxs_fcf_event_xlate(evt), arg1, 7260 vfip->flag); 7261 return (1); 7262 } 7263 7264 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); 7265 7266 if (vfip->prev_state == VFI_STATE_OFFLINE) { 7267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7268 "vfi_offline_action:%d vfi_online=%d. Terminated.", 7269 vfip->VFI, 7270 vfip->fcfp->vfi_online); 7271 7272 return (0); 7273 } 7274 7275 if (vfip->vpi_online) { 7276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7277 "vfi_offline_action:%d vpi_online=%d. VPI's still online.", 7278 vfip->VFI, 7279 vfip->vpi_online); 7280 } 7281 7282 if (vfip->flag & EMLXS_VFI_FCFI) { 7283 vfip->flag &= ~EMLXS_VFI_FCFI; 7284 7285 if (vfip->fcfp->vfi_online) { 7286 vfip->fcfp->vfi_online--; 7287 } 7288 } 7289 7290 /* Check if online was requested */ 7291 if (vfip->flag & EMLXS_VFI_ONLINE_REQ) { 7292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7293 "vfi_offline_action:%d vfi_online=%d. Online requested.", 7294 vfip->VFI, 7295 vfip->fcfp->vfi_online); 7296 7297 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, 7298 FCF_REASON_REQUESTED, 0, arg1); 7299 return (rval); 7300 } 7301 7302 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7303 "vfi_offline_action:%d vfi_online=%d. " 7304 "VFI offline. Notifying FCFI:%d", 7305 vfip->VFI, 7306 vfip->fcfp->vfi_online, 7307 vfip->fcfp->fcf_index); 7308 7309 /* Notify FCFI */ 7310 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip); 7311 7312 return (rval); 7313 7314 } /* emlxs_vfi_offline_action() */ 7315 7316 7317 /*ARGSUSED*/ 7318 static uint32_t 7319 emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 7320 { 7321 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 7322 VFIobj_t *vfip; 7323 MAILBOX4 *mb4; 7324 7325 vfip = (VFIobj_t *)mbq->context; 7326 mb4 = (MAILBOX4 *)mbq; 7327 7328 mutex_enter(&EMLXS_FCF_LOCK); 7329 7330 if (vfip->state != VFI_STATE_INIT) { 7331 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7332 "vfi_init_mbcmpl:%d %s. Terminated.", 7333 vfip->VFI, 7334 emlxs_vfi_state_xlate(vfip->state)); 7335 7336 mutex_exit(&EMLXS_FCF_LOCK); 7337 return (0); 7338 } 7339 7340 if (mb4->mbxStatus) { 7341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7342 "vfi_init_mbcmpl:%d failed. status=%x", 7343 vfip->VFI, 7344 mb4->mbxStatus); 7345 7346 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED, 7347 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 7348 7349 mutex_exit(&EMLXS_FCF_LOCK); 7350 return (0); 7351 } 7352 7353 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7354 "vfi_init_mbcmpl:%d Initialized.", 7355 vfip->VFI, 7356 mb4->mbxStatus); 7357 7358 vfip->flag |= EMLXS_VFI_INIT; 7359 (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0); 7360 7361 mutex_exit(&EMLXS_FCF_LOCK); 7362 return (0); 7363 7364 } /* emlxs_vfi_init_mbcmpl() */ 7365 7366 7367 /*ARGSUSED*/ 7368 static uint32_t 7369 emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7370 void *arg1) 7371 { 7372 emlxs_hba_t *hba = HBA; 7373 MAILBOXQ *mbq; 7374 MAILBOX4 *mb4; 7375 uint32_t rval; 7376 7377 if (vfip->state != VFI_STATE_INIT) { 7378 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7379 "vfi_init_action:%d %s:%s arg=%p. " 7380 "Invalid state. Terminated.", 7381 vfip->VFI, 7382 emlxs_vfi_state_xlate(vfip->state), 7383 emlxs_fcf_event_xlate(evt), arg1); 7384 return (1); 7385 } 7386 7387 if (!(vfip->flag & EMLXS_VFI_FCFI)) { 7388 vfip->flag |= EMLXS_VFI_FCFI; 7389 vfip->fcfp->vfi_online++; 7390 } 7391 7392 if (vfip->prev_state != VFI_STATE_INIT_FAILED) { 7393 vfip->attempts = 0; 7394 } 7395 7396 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 7397 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7398 "vfi_init_action:%d attempts=%d. Offline requested.", 7399 vfip->VFI, 7400 vfip->attempts); 7401 7402 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 7403 return (rval); 7404 } 7405 7406 if (vfip->flag & EMLXS_VFI_INIT) { 7407 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7408 "vfi_init_action:%d flag=%x. " 7409 "Already init'd. Skipping init.", 7410 vfip->VFI); 7411 7412 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, 7413 FCF_REASON_EVENT, evt, arg1); 7414 return (rval); 7415 } 7416 7417 if (vfip->fcfp->vfi_online == 1) { 7418 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7419 "vfi_init_action:%d vfi_online=%d. Skipping init.", 7420 vfip->VFI, 7421 vfip->fcfp->vfi_online); 7422 7423 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, 7424 FCF_REASON_EVENT, evt, arg1); 7425 return (rval); 7426 } 7427 7428 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7429 "vfi_init_action:%d vfi_online=%d attempts=%d", 7430 vfip->VFI, 7431 vfip->fcfp->vfi_online, 7432 vfip->attempts); 7433 7434 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 7435 rval = emlxs_vfi_state(port, vfip, FCFI_STATE_REG_FAILED, 7436 FCF_REASON_NO_MBOX, 0, arg1); 7437 return (rval); 7438 } 7439 mb4 = (MAILBOX4*)mbq; 7440 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 7441 7442 mbq->nonembed = NULL; 7443 mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl; 7444 mbq->context = (void *)vfip; 7445 mbq->port = (void *)port; 7446 7447 mb4->mbxCommand = MBX_INIT_VFI; 7448 mb4->mbxOwner = OWN_HOST; 7449 mb4->un.varInitVFI4.fcfi = vfip->fcfp->FCFI; 7450 mb4->un.varInitVFI4.vfi = vfip->VFI; 7451 7452 /* ??? This function is untested and incomplete */ 7453 7454 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 7455 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 7456 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 7457 7458 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED, 7459 FCF_REASON_SEND_FAILED, rval, arg1); 7460 7461 return (rval); 7462 } 7463 7464 return (0); 7465 7466 } /* emlxs_vfi_init_action() */ 7467 7468 7469 /*ARGSUSED*/ 7470 static uint32_t 7471 emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7472 void *arg1) 7473 { 7474 uint32_t rval; 7475 7476 vfip->attempts++; 7477 7478 if (vfip->state != VFI_STATE_INIT_FAILED) { 7479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7480 "vfi_init_action:%d %s:%s arg=%p attempt=%d. " 7481 "Invalid state. Terminated.", 7482 vfip->VFI, 7483 emlxs_vfi_state_xlate(vfip->state), 7484 emlxs_fcf_event_xlate(evt), arg1, 7485 vfip->attempts); 7486 7487 return (1); 7488 } 7489 7490 if ((vfip->reason == FCF_REASON_SEND_FAILED) || 7491 (vfip->attempts >= 3)) { 7492 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7493 "vfi_init_action:%d attempt=%d reason=%x. Init cmpl.", 7494 vfip->VFI, 7495 vfip->attempts, 7496 vfip->reason); 7497 7498 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); 7499 7500 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7501 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 7502 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 7503 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 7504 } else { 7505 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7506 "vfi_init_action:%d attempt=%d. Initializing.", 7507 vfip->VFI, 7508 vfip->attempts); 7509 7510 rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, 7511 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 7512 } 7513 7514 return (rval); 7515 7516 } /* emlxs_vfi_init_failed_action() */ 7517 7518 7519 /*ARGSUSED*/ 7520 static uint32_t 7521 emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7522 void *arg1) 7523 { 7524 uint32_t rval; 7525 7526 if (vfip->state != VFI_STATE_INIT_CMPL) { 7527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7528 "vfi_init_cmpl_action:%d %s:%s arg=%p. " 7529 "Invalid state. Terminated.", 7530 vfip->VFI, 7531 emlxs_vfi_state_xlate(vfip->state), 7532 emlxs_fcf_event_xlate(evt), arg1); 7533 return (1); 7534 } 7535 7536 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7537 "vfi_init_cmpl_action:%d attempts=%d. Init cmpl.", 7538 vfip->VFI, 7539 vfip->attempts); 7540 7541 rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, 7542 FCF_REASON_EVENT, evt, arg1); 7543 7544 return (rval); 7545 7546 } /* emlxs_vfi_init_cmpl_action() */ 7547 7548 7549 /*ARGSUSED*/ 7550 static uint32_t 7551 emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7552 void *arg1) 7553 { 7554 emlxs_hba_t *hba = HBA; 7555 uint32_t rval; 7556 uint32_t i; 7557 emlxs_port_t *vport; 7558 VPIobj_t *vpip; 7559 7560 if (vfip->state != VFI_STATE_VPI_ONLINE) { 7561 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7562 "vfi_vpi_online_action:%d %s:%s arg=%p. " 7563 "Invalid state. Terminated.", 7564 vfip->VFI, 7565 emlxs_vfi_state_xlate(vfip->state), 7566 emlxs_fcf_event_xlate(evt), arg1); 7567 return (1); 7568 } 7569 7570 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 7571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7572 "vfi_vpi_online_action:%d. Offline requested.", 7573 vfip->VFI); 7574 7575 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 7576 return (rval); 7577 } 7578 7579 if (vfip->logi_count > 0) { 7580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7581 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " 7582 "VPI already logged in.", 7583 vfip->VFI, 7584 vfip->vpi_online, 7585 vfip->logi_count); 7586 } 7587 7588 if (vfip->vpi_online > 0) { 7589 /* Waking up out after being paused */ 7590 7591 /* Find first VPI of this VFI */ 7592 for (i = 0; i <= hba->vpi_max; i++) { 7593 vport = &VPORT(i); 7594 vpip = &vport->VPIobj; 7595 7596 if (!(vport->flag & EMLXS_PORT_BOUND)) { 7597 continue; 7598 } 7599 7600 if (vpip->vfip == vfip) { 7601 break; 7602 } 7603 } 7604 7605 } else { 7606 7607 /* Find first available VPI */ 7608 for (i = 0; i <= hba->vpi_max; i++) { 7609 vport = &VPORT(i); 7610 vpip = &vport->VPIobj; 7611 7612 if (!(vport->flag & EMLXS_PORT_BOUND)) { 7613 continue; 7614 } 7615 7616 if (vpip->vfip == NULL) { 7617 vpip->vfip = vfip; 7618 break; 7619 } 7620 } 7621 } 7622 7623 if (i > hba->vpi_max) { 7624 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7625 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " 7626 "No VPI found. Offlining.", 7627 vfip->VFI, 7628 vfip->vpi_online, 7629 vfip->logi_count); 7630 7631 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7632 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 7633 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 7634 return (rval); 7635 } 7636 7637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7638 "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " 7639 "Onlining VPI:%d", 7640 vfip->VFI, 7641 vfip->vpi_online, 7642 vfip->logi_count, 7643 vpip->VPI); 7644 7645 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip); 7646 7647 /* Wait for FCF_EVENT_VPI_ONLINE in return */ 7648 7649 return (rval); 7650 7651 } /* emlxs_vfi_vpi_online_action() */ 7652 7653 7654 /*ARGSUSED*/ 7655 static uint32_t 7656 emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, 7657 uint32_t evt, void *arg1) 7658 { 7659 uint32_t rval; 7660 7661 if (vfip->state != VFI_STATE_VPI_ONLINE_CMPL) { 7662 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7663 "vfi_vpi_online_cmpl_action:%d %s:%s arg=%p. " 7664 "Invalid state. Terminated.", 7665 vfip->VFI, 7666 emlxs_vfi_state_xlate(vfip->state), 7667 emlxs_fcf_event_xlate(evt), arg1); 7668 return (1); 7669 } 7670 7671 if (vfip->vpi_online > 1) { 7672 /* Waking up after pause */ 7673 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7674 "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d " 7675 "logi_count=%d. Going online.", 7676 vfip->VFI, 7677 vfip->flag, 7678 vfip->vpi_online, 7679 vfip->logi_count); 7680 7681 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, 7682 FCF_REASON_EVENT, evt, arg1); 7683 } else { 7684 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7685 "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d " 7686 "logi_count=%d. Registering.", 7687 vfip->VFI, 7688 vfip->flag, 7689 vfip->vpi_online, 7690 vfip->logi_count); 7691 7692 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG, 7693 FCF_REASON_EVENT, evt, arg1); 7694 } 7695 7696 return (rval); 7697 7698 } /* emlxs_vfi_vpi_online_cmpl_action() */ 7699 7700 7701 /*ARGSUSED*/ 7702 static uint32_t 7703 emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, 7704 uint32_t evt, void *arg1) 7705 { 7706 uint32_t rval = 0; 7707 7708 if (vfip->state != VFI_STATE_VPI_OFFLINE_CMPL) { 7709 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7710 "vfi_vpi_offline_cmpl_action:%d %s:%s arg=%p. " 7711 "Invalid state. Terminated.", 7712 vfip->VFI, 7713 emlxs_vfi_state_xlate(vfip->state), 7714 emlxs_fcf_event_xlate(evt), arg1); 7715 return (1); 7716 } 7717 7718 if ((vfip->vpi_online == 0) && 7719 (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { 7720 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7721 "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. " 7722 "Unregistering.", 7723 vfip->VFI, 7724 vfip->vpi_online); 7725 7726 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, 7727 FCF_REASON_EVENT, evt, arg1); 7728 } else { 7729 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7730 "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. Terminated.", 7731 vfip->VFI, 7732 vfip->vpi_online); 7733 } 7734 7735 return (rval); 7736 7737 } /* emlxs_vfi_vpi_offline_cmpl_action() */ 7738 7739 7740 /*ARGSUSED*/ 7741 static uint32_t 7742 emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7743 void *arg1) 7744 { 7745 emlxs_hba_t *hba = HBA; 7746 emlxs_port_t *vport; 7747 uint32_t rval; 7748 int32_t i; 7749 VPIobj_t *vpip; 7750 7751 if (vfip->state != VFI_STATE_VPI_OFFLINE) { 7752 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7753 "vfi_vpi_offline_action:%d %s:%s arg=%p. " 7754 "Invalid state. Terminated.", 7755 vfip->VFI, 7756 emlxs_vfi_state_xlate(vfip->state), 7757 emlxs_fcf_event_xlate(evt), arg1); 7758 return (1); 7759 } 7760 7761 if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { 7762 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7763 "vfi_vpi_offline_action:%d vpi_online=%d. Pausing.", 7764 vfip->VFI, 7765 vfip->vpi_online); 7766 7767 rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED, 7768 FCF_REASON_EVENT, evt, arg1); 7769 7770 return (rval); 7771 } 7772 7773 if (vfip->vpi_online == 0) { 7774 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7775 "vfi_vpi_offline_action:%d vpi_online=%d. " 7776 "VPI already offline. Skipping offline.", 7777 vfip->VFI, 7778 vfip->vpi_online); 7779 7780 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, 7781 FCF_REASON_EVENT, evt, arg1); 7782 7783 return (rval); 7784 } 7785 7786 /* Offline all VPI's of this VFI */ 7787 for (i = hba->vpi_max; i >= 0; i--) { 7788 vport = &VPORT(i); 7789 vpip = &vport->VPIobj; 7790 7791 if ((vpip->state == VPI_STATE_OFFLINE) || 7792 (vpip->vfip != vfip)) { 7793 continue; 7794 } 7795 7796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7797 "vfi_vpi_offline_action:%d. Offlining VPI:%d.", 7798 vfip->VFI, 7799 vpip->VPI); 7800 7801 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip); 7802 } 7803 7804 /* Wait for FCF_EVENT_VPI_OFFLINE in return */ 7805 7806 return (0); 7807 7808 } /* emlxs_vfi_vpi_offline_action() */ 7809 7810 7811 /*ARGSUSED*/ 7812 static uint32_t 7813 emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7814 void *arg1) 7815 { 7816 emlxs_hba_t *hba = HBA; 7817 emlxs_port_t *vport; 7818 int32_t i; 7819 VPIobj_t *vpip; 7820 7821 if (vfip->state != VFI_STATE_PAUSED) { 7822 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7823 "vfi_paused_action:%d %s:%s arg=%p. " 7824 "Invalid state. Terminated.", 7825 vfip->VFI, 7826 emlxs_vfi_state_xlate(vfip->state), 7827 emlxs_fcf_event_xlate(evt), arg1); 7828 return (1); 7829 } 7830 7831 vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); 7832 7833 /* Pause all VPI's of this VFI */ 7834 for (i = hba->vpi_max; i >= 0; i--) { 7835 vport = &VPORT(i); 7836 vpip = &vport->VPIobj; 7837 7838 if ((vpip->state == VPI_STATE_PAUSED) || 7839 (vpip->vfip != vfip)) { 7840 continue; 7841 } 7842 7843 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7844 "vfi_paused_action:%d vpi_online=%d. Pausing VPI:%d.", 7845 vfip->VFI, 7846 vfip->vpi_online, 7847 vpip->VPI); 7848 7849 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip); 7850 } 7851 7852 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7853 "vfi_paused_action:%d vpi_online=%d. VFI paused.", 7854 vfip->VFI, 7855 vfip->vpi_online); 7856 7857 return (0); 7858 7859 } /* emlxs_vfi_paused_action() */ 7860 7861 7862 /*ARGSUSED*/ 7863 static uint32_t 7864 emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7865 void *arg1) 7866 { 7867 uint32_t rval; 7868 7869 vfip->attempts++; 7870 7871 if (vfip->state != VFI_STATE_UNREG_FAILED) { 7872 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7873 "vfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " 7874 "Invalid state. Terminated.", 7875 vfip->VFI, 7876 emlxs_vfi_state_xlate(vfip->state), 7877 emlxs_fcf_event_xlate(evt), arg1, 7878 vfip->attempts); 7879 7880 return (1); 7881 } 7882 7883 if (vfip->attempts >= 3) { 7884 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7885 "vfi_unreg_failed_action:%d attempt=%d. Unreg cmpl.", 7886 vfip->VFI, 7887 vfip->attempts); 7888 7889 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 7890 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 7891 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL, 7892 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 7893 } else { 7894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7895 "vfi_unreg_failed_action:%d attempt=%d. Unregistering.", 7896 vfip->VFI, 7897 vfip->attempts); 7898 7899 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, 7900 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 7901 } 7902 7903 return (rval); 7904 7905 } /* emlxs_vfi_unreg_failed_action() */ 7906 7907 7908 /*ARGSUSED*/ 7909 static uint32_t 7910 emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 7911 { 7912 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 7913 MAILBOX4 *mb4; 7914 VFIobj_t *vfip; 7915 7916 vfip = (VFIobj_t *)mbq->context; 7917 mb4 = (MAILBOX4 *)mbq; 7918 7919 mutex_enter(&EMLXS_FCF_LOCK); 7920 7921 if (vfip->state != VFI_STATE_UNREG) { 7922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7923 "vfi_unreg_mbcmpl:%d state=%s. Terminated.", 7924 vfip->VFI, 7925 emlxs_vfi_state_xlate(vfip->state)); 7926 7927 mutex_exit(&EMLXS_FCF_LOCK); 7928 return (0); 7929 } 7930 7931 if (mb4->mbxStatus) { 7932 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7933 "vfi_unreg_mbcmpl:%d failed. status=%x", 7934 vfip->VFI, 7935 mb4->mbxStatus); 7936 7937 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, 7938 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); 7939 7940 mutex_exit(&EMLXS_FCF_LOCK); 7941 return (0); 7942 } 7943 7944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7945 "vfi_unreg_mbcmpl:%d Unregistered.", 7946 vfip->VFI); 7947 7948 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); 7949 (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL, 7950 0, 0, 0); 7951 7952 mutex_exit(&EMLXS_FCF_LOCK); 7953 return (0); 7954 7955 } /* emlxs_vfi_unreg_mbcmpl() */ 7956 7957 7958 /*ARGSUSED*/ 7959 static uint32_t 7960 emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 7961 void *arg1) 7962 { 7963 emlxs_hba_t *hba = HBA; 7964 MAILBOX4 *mb4; 7965 MAILBOXQ *mbq; 7966 uint32_t rval; 7967 7968 if (vfip->state != VFI_STATE_UNREG) { 7969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 7970 "vfi_unreg_action:%d %s:%s arg=%p. " 7971 "Invalid state. Terminated.", 7972 vfip->VFI, 7973 emlxs_vfi_state_xlate(vfip->state), 7974 emlxs_fcf_event_xlate(evt), arg1); 7975 7976 return (1); 7977 } 7978 7979 if (!(vfip->flag & EMLXS_VFI_REG)) { 7980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7981 "vfi_unreg_action:%d. Not registered. Skipping unreg.", 7982 vfip->VFI); 7983 7984 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, 7985 FCF_REASON_EVENT, evt, arg1); 7986 return (rval); 7987 } 7988 7989 if (vfip->prev_state != VFI_STATE_UNREG_FAILED) { 7990 vfip->attempts = 0; 7991 } 7992 7993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 7994 "vfi_unreg_action:%d attempts=%d. Sending UNREG_VFI.", 7995 vfip->VFI, 7996 vfip->attempts); 7997 7998 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 7999 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, 8000 FCF_REASON_NO_MBOX, 0, arg1); 8001 8002 return (rval); 8003 } 8004 mb4 = (MAILBOX4*)mbq; 8005 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 8006 8007 mbq->nonembed = NULL; 8008 mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl; 8009 mbq->context = (void *)vfip; 8010 mbq->port = (void *)port; 8011 8012 mb4->un.varUnRegVFI4.vfi = vfip->VFI; 8013 mb4->mbxCommand = MBX_UNREG_VFI; 8014 mb4->mbxOwner = OWN_HOST; 8015 8016 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 8017 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 8018 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 8019 8020 rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, 8021 FCF_REASON_SEND_FAILED, rval, arg1); 8022 8023 return (rval); 8024 } 8025 8026 return (0); 8027 8028 } /* emlxs_vfi_unreg_action() */ 8029 8030 8031 /*ARGSUSED*/ 8032 static uint32_t 8033 emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 8034 void *arg1) 8035 { 8036 uint32_t rval; 8037 8038 if (vfip->state != VFI_STATE_UNREG_CMPL) { 8039 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8040 "vfi_unreg_cmpl_action:%d %s:%s arg=%p. " 8041 "Invalid state. Terminated.", 8042 vfip->VFI, 8043 emlxs_vfi_state_xlate(vfip->state), 8044 emlxs_fcf_event_xlate(evt), arg1); 8045 return (1); 8046 } 8047 8048 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8049 "vfi_unreg_cmpl_action:%d attempts=%d. Going offline.", 8050 vfip->VFI, 8051 vfip->attempts); 8052 8053 rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, 8054 FCF_REASON_EVENT, evt, arg1); 8055 8056 return (rval); 8057 8058 } /* emlxs_vfi_unreg_cmpl_action() */ 8059 8060 8061 /*ARGSUSED*/ 8062 static uint32_t 8063 emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 8064 void *arg1) 8065 { 8066 uint32_t rval; 8067 8068 vfip->attempts++; 8069 8070 if (vfip->state != VFI_STATE_REG_FAILED) { 8071 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8072 "vfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " 8073 "Invalid state. Terminated.", 8074 vfip->VFI, 8075 emlxs_vfi_state_xlate(vfip->state), 8076 emlxs_fcf_event_xlate(evt), arg1, 8077 vfip->attempts); 8078 8079 return (1); 8080 } 8081 8082 if ((vfip->reason == FCF_REASON_SEND_FAILED) || 8083 (vfip->attempts >= 3)) { 8084 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8085 "vfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", 8086 vfip->VFI, 8087 vfip->attempts, 8088 vfip->reason); 8089 8090 vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); 8091 8092 vfip->flag &= ~EMLXS_VFI_REQ_MASK; 8093 vfip->flag |= EMLXS_VFI_OFFLINE_REQ; 8094 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 8095 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 8096 } else { 8097 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8098 "vfi_reg_failed_action:%d attempt=%d. Registering.", 8099 vfip->VFI, 8100 vfip->attempts); 8101 8102 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG, 8103 FCF_REASON_OP_FAILED, vfip->attempts, arg1); 8104 } 8105 8106 return (rval); 8107 8108 } /* emlxs_vfi_reg_failed_action() */ 8109 8110 8111 /*ARGSUSED*/ 8112 static uint32_t 8113 emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 8114 { 8115 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 8116 MAILBOX4 *mb4; 8117 VFIobj_t *vfip; 8118 8119 vfip = (VFIobj_t *)mbq->context; 8120 mb4 = (MAILBOX4 *)mbq; 8121 8122 mutex_enter(&EMLXS_FCF_LOCK); 8123 8124 if (vfip->state != VFI_STATE_REG) { 8125 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8126 "vfi_reg_mbcmpl:%d state=%s. Terminated.", 8127 vfip->VFI, 8128 emlxs_vfi_state_xlate(vfip->state)); 8129 8130 mutex_exit(&EMLXS_FCF_LOCK); 8131 return (0); 8132 } 8133 8134 if (mb4->mbxStatus) { 8135 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8136 "vfi_reg_mbcmpl:%d failed. status=%x", 8137 vfip->VFI, 8138 mb4->mbxStatus); 8139 8140 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, 8141 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); 8142 8143 mutex_exit(&EMLXS_FCF_LOCK); 8144 return (0); 8145 } 8146 8147 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8148 "vfi_reg_mbcmpl:%d Registered.", 8149 vfip->VFI); 8150 8151 if (vfip->vpi_online == 1) { 8152 port->VPIobj.flag |= EMLXS_VPI_REG; 8153 } 8154 8155 vfip->flag |= EMLXS_VFI_REG; 8156 8157 (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0); 8158 8159 mutex_exit(&EMLXS_FCF_LOCK); 8160 return (0); 8161 8162 } /* emlxs_vfi_reg_mbcmpl() */ 8163 8164 8165 /*ARGSUSED*/ 8166 static uint32_t 8167 emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 8168 void *arg1) 8169 { 8170 emlxs_hba_t *hba = HBA; 8171 FCFIobj_t *fcfp; 8172 MAILBOX4 *mb4; 8173 MAILBOXQ *mbq; 8174 MATCHMAP *mp; 8175 uint32_t rval; 8176 uint32_t edtov; 8177 uint32_t ratov; 8178 8179 if (vfip->state != VFI_STATE_REG) { 8180 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8181 "vfi_reg_action:%d %s:%s arg=%p. " 8182 "Invalid state. Terminated.", 8183 vfip->VFI, 8184 emlxs_vfi_state_xlate(vfip->state), 8185 emlxs_fcf_event_xlate(evt), arg1); 8186 8187 return (1); 8188 } 8189 8190 if (vfip->prev_state != VFI_STATE_REG_FAILED) { 8191 vfip->attempts = 0; 8192 } 8193 8194 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 8195 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8196 "vfi_reg_action:%d %attempts=%d. Offline requested.", 8197 vfip->VFI, 8198 vfip->attempts); 8199 8200 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 8201 return (rval); 8202 } 8203 8204 if (vfip->flag & EMLXS_VFI_REG) { 8205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8206 "vfi_reg_action:%d flag=%x. " 8207 "Already registered. Skipping reg.", 8208 vfip->VFI); 8209 8210 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, 8211 FCF_REASON_EVENT, evt, arg1); 8212 return (rval); 8213 } 8214 8215 if (vfip->fcf_sparam.cmn.edtovResolution) { 8216 edtov = (LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov) + 999999) / 8217 1000000; 8218 } else { 8219 edtov = LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov); 8220 } 8221 8222 ratov = (LE_SWAP32(vfip->fcf_sparam.cmn.w2.r_a_tov) + 999) / 1000; 8223 8224 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8225 "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. " 8226 "Sending REG_VFI.", 8227 vfip->VFI, 8228 vfip->attempts, 8229 edtov, ratov); 8230 8231 fcfp = vfip->fcfp; 8232 8233 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 8234 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, 8235 FCF_REASON_NO_MBOX, 0, arg1); 8236 8237 return (rval); 8238 } 8239 mb4 = (MAILBOX4*)mbq; 8240 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 8241 8242 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 8243 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 8244 8245 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, 8246 FCF_REASON_NO_BUFFER, 0, arg1); 8247 8248 return (1); 8249 } 8250 8251 mbq->bp = (void *)mp; 8252 mbq->nonembed = NULL; 8253 8254 mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl; 8255 mbq->context = (void *)vfip; 8256 mbq->port = (void *)port; 8257 8258 mb4->mbxCommand = MBX_REG_VFI; 8259 mb4->mbxOwner = OWN_HOST; 8260 mb4->un.varRegVFI4.vfi = vfip->VFI; 8261 8262 if (vfip->fcfp->vfi_online == 1) { 8263 mb4->un.varRegVFI4.vp = 1; 8264 mb4->un.varRegVFI4.vpi = port->VPIobj.VPI; 8265 } 8266 8267 mb4->un.varRegVFI4.fcfi = fcfp->FCFI; 8268 mb4->un.varRegVFI4.sid = port->did; 8269 mb4->un.varRegVFI4.edtov = edtov; 8270 8271 /* Convert to seconds */ 8272 mb4->un.varRegVFI4.ratov = ratov; 8273 mb4->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM); 8274 mb4->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys); 8275 mb4->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys); 8276 bcopy((uint32_t *)&vfip->fcf_sparam, 8277 (uint32_t *)mp->virt, sizeof (SERV_PARM)); 8278 8279 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 8280 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 8281 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 8282 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 8283 8284 rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, 8285 FCF_REASON_SEND_FAILED, rval, arg1); 8286 8287 return (rval); 8288 } 8289 8290 return (0); 8291 8292 } /* emlxs_vfi_reg_action() */ 8293 8294 8295 /*ARGSUSED*/ 8296 static uint32_t 8297 emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 8298 void *arg1) 8299 { 8300 uint32_t rval; 8301 8302 if (vfip->state != VFI_STATE_REG_CMPL) { 8303 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8304 "vfi_reg_cmpl_action:%d %s:%s arg=%p. " 8305 "Invalid state. Terminated.", 8306 vfip->VFI, 8307 emlxs_vfi_state_xlate(vfip->state), 8308 emlxs_fcf_event_xlate(evt), arg1); 8309 return (1); 8310 } 8311 8312 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 8313 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8314 "vfi_reg_cmpl_action:%d attempts=%d. Offline requested.", 8315 vfip->VFI, 8316 vfip->attempts); 8317 8318 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 8319 return (rval); 8320 } 8321 8322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8323 "vfi_reg_cmpl_action:%d attempts=%d. Going online.", 8324 vfip->VFI, 8325 vfip->attempts); 8326 8327 rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, 8328 FCF_REASON_EVENT, evt, arg1); 8329 8330 return (rval); 8331 8332 } /* emlxs_vfi_reg_cmpl_action() */ 8333 8334 8335 /*ARGSUSED*/ 8336 static uint32_t 8337 emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, 8338 void *arg1) 8339 { 8340 emlxs_hba_t *hba = HBA; 8341 uint32_t i; 8342 uint32_t rval; 8343 VPIobj_t *vpip; 8344 emlxs_port_t *vport; 8345 8346 if (vfip->state != VFI_STATE_ONLINE) { 8347 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8348 "vfi_online_action:%d %s:%s arg=%p. " 8349 "Invalid state. Terminated.", 8350 vfip->VFI, 8351 emlxs_vfi_state_xlate(vfip->state), 8352 emlxs_fcf_event_xlate(evt), arg1); 8353 return (1); 8354 } 8355 8356 vfip->flag &= ~EMLXS_VFI_ONLINE_REQ; 8357 8358 if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { 8359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8360 "vfi_online_action:%d attempts=%d. Offline requested.", 8361 vfip->VFI, 8362 vfip->attempts); 8363 8364 rval = emlxs_vfi_offline_handler(port, vfip, arg1); 8365 return (rval); 8366 } 8367 8368 vpip = &port->VPIobj; 8369 8370 /* Take Fabric RPI online now */ 8371 if (vpip->rpip->state != RPI_STATE_ONLINE) { 8372 /* This will complete the FLOGI/FDISC back to Leadville */ 8373 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, vpip->rpip); 8374 } 8375 8376 /* FLOGI/FDISC has been completed back to Leadville */ 8377 /* It is now safe to accept unsolicited requests */ 8378 vpip->flag |= EMLXS_VPI_PORT_ENABLED; 8379 8380 /* Online remaining VPI's */ 8381 for (i = 0; i <= hba->vpi_max; i++) { 8382 vport = &VPORT(i); 8383 vpip = &vport->VPIobj; 8384 8385 if (!(vport->flag & EMLXS_PORT_BOUND)) { 8386 continue; 8387 } 8388 8389 if ((vpip->state == VPI_STATE_ONLINE) || 8390 (vpip->flag & EMLXS_VPI_ONLINE_REQ)) { 8391 continue; 8392 } 8393 8394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8395 "vfi_online_action:%d vpi_online=%d logi_count=%d. " 8396 "Onlining VPI:%d", 8397 vfip->VFI, 8398 vfip->vpi_online, 8399 vfip->logi_count, 8400 vpip->VPI); 8401 8402 vpip->vfip = vfip; 8403 (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip); 8404 } 8405 8406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8407 "vfi_online_action:%d vpi_online=%d logi_count=%d. " 8408 "VFI online. Notifying FCFI:%d.", 8409 vfip->VFI, 8410 vfip->vpi_online, 8411 vfip->logi_count, 8412 vfip->fcfp->fcf_index); 8413 8414 /* Notify FCFI */ 8415 rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); 8416 8417 return (rval); 8418 8419 } /* emlxs_vfi_online_action() */ 8420 8421 8422 /* ************************************************************************** */ 8423 /* VPI */ 8424 /* ************************************************************************** */ 8425 8426 static char * 8427 emlxs_vpi_state_xlate(uint32_t state) 8428 { 8429 static char buffer[32]; 8430 uint32_t i; 8431 uint32_t count; 8432 8433 count = sizeof (emlxs_vpi_state_table) / sizeof (emlxs_table_t); 8434 for (i = 0; i < count; i++) { 8435 if (state == emlxs_vpi_state_table[i].code) { 8436 return (emlxs_vpi_state_table[i].string); 8437 } 8438 } 8439 8440 (void) sprintf(buffer, "state=0x%x", state); 8441 return (buffer); 8442 8443 } /* emlxs_vpi_state_xlate() */ 8444 8445 8446 static uint32_t 8447 emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 8448 void *arg1) 8449 { 8450 uint32_t rval; 8451 uint32_t(*func) (emlxs_port_t *, VPIobj_t *, uint32_t, void *); 8452 uint32_t index; 8453 uint32_t events; 8454 uint16_t state; 8455 8456 /* Convert event to action table index */ 8457 switch (evt) { 8458 case FCF_EVENT_STATE_ENTER: 8459 index = 0; 8460 break; 8461 case FCF_EVENT_VPI_ONLINE: 8462 index = 1; 8463 break; 8464 case FCF_EVENT_VPI_OFFLINE: 8465 index = 2; 8466 break; 8467 case FCF_EVENT_VPI_PAUSE: 8468 index = 3; 8469 break; 8470 case FCF_EVENT_RPI_ONLINE: 8471 index = 4; 8472 break; 8473 case FCF_EVENT_RPI_OFFLINE: 8474 index = 5; 8475 break; 8476 case FCF_EVENT_RPI_PAUSE: 8477 index = 6; 8478 break; 8479 default: 8480 return (1); 8481 } 8482 8483 events = VPI_ACTION_EVENTS; 8484 state = vpip->state; 8485 8486 index += (state * events); 8487 func = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *)) 8488 emlxs_vpi_action_table[index]; 8489 8490 if (!func) { 8491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 8492 "vpi:%d %s:%s arg=%p. No action. Terminated.", 8493 vpip->VPI, 8494 emlxs_vpi_state_xlate(vpip->state), 8495 emlxs_fcf_event_xlate(evt), arg1); 8496 8497 return (1); 8498 } 8499 8500 rval = (func)(port, vpip, evt, arg1); 8501 8502 return (rval); 8503 8504 } /* emlxs_vpi_action() */ 8505 8506 8507 static uint32_t 8508 emlxs_vpi_event(emlxs_port_t *port, uint32_t evt, 8509 void *arg1) 8510 { 8511 VPIobj_t *vpip = NULL; 8512 RPIobj_t *rpip; 8513 uint32_t rval; 8514 8515 /* Filter events and acquire fcfi context */ 8516 switch (evt) { 8517 case FCF_EVENT_RPI_ONLINE: 8518 case FCF_EVENT_RPI_OFFLINE: 8519 case FCF_EVENT_RPI_PAUSE: 8520 rpip = (RPIobj_t *)arg1; 8521 8522 if (!rpip) { 8523 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 8524 "rpi: %s arg=%p. Null RPI found. Terminated.", 8525 emlxs_fcf_event_xlate(evt), arg1); 8526 8527 return (1); 8528 } 8529 8530 vpip = rpip->vpip; 8531 break; 8532 8533 case FCF_EVENT_VPI_ONLINE: 8534 case FCF_EVENT_VPI_PAUSE: 8535 case FCF_EVENT_VPI_OFFLINE: 8536 vpip = (VPIobj_t *)arg1; 8537 8538 if (!vpip) { 8539 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 8540 "vpi: %s arg=%p. Null VPI found. Terminated.", 8541 emlxs_fcf_event_xlate(evt), arg1); 8542 8543 return (1); 8544 } 8545 8546 break; 8547 8548 default: 8549 return (1); 8550 } 8551 8552 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 8553 "vpi:%d %s:%s arg=%p", 8554 vpip->VPI, 8555 emlxs_vpi_state_xlate(vpip->state), 8556 emlxs_fcf_event_xlate(evt), arg1); 8557 8558 rval = emlxs_vpi_action(port, vpip, evt, arg1); 8559 8560 return (rval); 8561 8562 } /* emlxs_vpi_event() */ 8563 8564 8565 /*ARGSUSED*/ 8566 static uint32_t 8567 emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state, 8568 uint16_t reason, uint32_t explain, void *arg1) 8569 { 8570 uint32_t rval = 0; 8571 8572 if (state >= VPI_ACTION_STATES) { 8573 return (1); 8574 } 8575 8576 if ((vpip->state == state) && 8577 (reason != FCF_REASON_REENTER)) { 8578 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8579 "vpi_state:%d %s:%s:0x%x arg=%p. " 8580 "State not changed. Terminated.", 8581 vpip->VPI, 8582 emlxs_vpi_state_xlate(vpip->state), 8583 emlxs_fcf_reason_xlate(reason), 8584 explain, arg1); 8585 8586 return (1); 8587 } 8588 8589 if (!reason) { 8590 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 8591 "vpi:%d %s-->%s arg=%p", 8592 vpip->VPI, 8593 emlxs_vpi_state_xlate(vpip->state), 8594 emlxs_vpi_state_xlate(state), arg1); 8595 } else if (reason == FCF_REASON_EVENT) { 8596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 8597 "vpi:%d %s-->%s:%s:%s arg=%p", 8598 vpip->VPI, 8599 emlxs_vpi_state_xlate(vpip->state), 8600 emlxs_vpi_state_xlate(state), 8601 emlxs_fcf_reason_xlate(reason), 8602 emlxs_fcf_event_xlate(explain), arg1); 8603 } else if (explain) { 8604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 8605 "vpi:%d %s-->%s:%s:0x%x arg=%p", 8606 vpip->VPI, 8607 emlxs_vpi_state_xlate(vpip->state), 8608 emlxs_vpi_state_xlate(state), 8609 emlxs_fcf_reason_xlate(reason), 8610 explain, arg1); 8611 } else { 8612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 8613 "vpi:%d %s-->%s:%s arg=%p", 8614 vpip->VPI, 8615 emlxs_vpi_state_xlate(vpip->state), 8616 emlxs_vpi_state_xlate(state), 8617 emlxs_fcf_reason_xlate(reason), arg1); 8618 } 8619 8620 vpip->prev_state = vpip->state; 8621 vpip->prev_reason = vpip->reason; 8622 vpip->state = state; 8623 vpip->reason = reason; 8624 8625 rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1); 8626 8627 return (rval); 8628 8629 } /* emlxs_vpi_state() */ 8630 8631 8632 extern uint32_t 8633 emlxs_vpi_port_bind_notify(emlxs_port_t *port) 8634 { 8635 emlxs_hba_t *hba = HBA; 8636 VPIobj_t *vpip = &port->VPIobj; 8637 FCFTable_t *fcftab = &hba->sli.sli4.fcftab; 8638 uint32_t rval = 0; 8639 VFIobj_t *vfip; 8640 VFIobj_t *vfip1; 8641 uint32_t i; 8642 FCFIobj_t *fcfp; 8643 FCFIobj_t *fcfp1; 8644 8645 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 8646 return (1); 8647 } 8648 8649 if (hba->state < FC_LINK_UP) { 8650 if (port->vpi == 0) { 8651 (void) emlxs_reset_link(hba, 1, 0); 8652 } 8653 return (0); 8654 } 8655 8656 mutex_enter(&EMLXS_FCF_LOCK); 8657 8658 if (vpip->vfip) { 8659 vfip = vpip->vfip; 8660 fcfp = vfip->fcfp; 8661 goto done; 8662 } 8663 8664 /* We need to select a VFI for this VPI */ 8665 8666 /* First find a selected Fabric */ 8667 fcfp = NULL; 8668 for (i = 0; i < fcftab->fcfi_count; i++) { 8669 fcfp1 = fcftab->fcfi[i]; 8670 8671 if (fcfp1->flag & EMLXS_FCFI_SELECTED) { 8672 fcfp = fcfp1; 8673 break; 8674 } 8675 } 8676 8677 if (!fcfp) { 8678 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8679 "vpi_port_bind_notify:%d %s. " 8680 "No FCF available yet. Terminated.", 8681 vpip->VPI, 8682 emlxs_vpi_state_xlate(vpip->state)); 8683 8684 mutex_exit(&EMLXS_FCF_LOCK); 8685 return (0); 8686 } 8687 8688 /* Find first available VFI for this FCFI */ 8689 vfip = NULL; 8690 vfip1 = hba->sli.sli4.VFI_table; 8691 for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip1++) { 8692 if (vfip1->fcfp == fcfp) { 8693 vfip = vfip1; 8694 break; 8695 } 8696 } 8697 8698 if (!vfip) { 8699 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8700 "vpi_port_bind_notify:%d %s fcfi:%d. " 8701 "No VFI available yet. Terminated.", 8702 vpip->VPI, 8703 emlxs_vpi_state_xlate(vpip->state), 8704 fcfp->fcf_index); 8705 8706 mutex_exit(&EMLXS_FCF_LOCK); 8707 return (0); 8708 } 8709 8710 vpip->vfip = vfip; 8711 done: 8712 8713 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8714 "vpi_port_bind_notify:%d %s fcfi:%d vfi:%d. Onlining VPI:%d", 8715 vpip->VPI, 8716 emlxs_vpi_state_xlate(vpip->state), 8717 fcfp->fcf_index, 8718 vfip->VFI, 8719 vpip->VPI); 8720 8721 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip); 8722 8723 mutex_exit(&EMLXS_FCF_LOCK); 8724 8725 return (rval); 8726 8727 } /* emlxs_vpi_port_bind_notify() */ 8728 8729 8730 extern uint32_t 8731 emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait) 8732 { 8733 emlxs_hba_t *hba = HBA; 8734 VPIobj_t *vpip = &port->VPIobj; 8735 uint32_t rval = 0; 8736 VFIobj_t *vfip; 8737 uint32_t i; 8738 FCFIobj_t *fcfp; 8739 8740 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 8741 return (1); 8742 } 8743 8744 mutex_enter(&EMLXS_FCF_LOCK); 8745 8746 if (vpip->state == VPI_STATE_OFFLINE) { 8747 mutex_exit(&EMLXS_FCF_LOCK); 8748 return (0); 8749 } 8750 8751 vfip = vpip->vfip; 8752 fcfp = vfip->fcfp; 8753 8754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8755 "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d. " 8756 "Offlining VPI:%d,%d", 8757 vpip->VPI, 8758 emlxs_vpi_state_xlate(vpip->state), 8759 fcfp->fcf_index, 8760 vfip->VFI, 8761 vpip->index, vpip->VPI); 8762 8763 rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); 8764 8765 if (wait && (rval == 0)) { 8766 /* Wait for VPI to go offline */ 8767 i = 0; 8768 while (i++ < 120) { 8769 if (vpip->state == VPI_STATE_OFFLINE) { 8770 break; 8771 } 8772 8773 mutex_exit(&EMLXS_FCF_LOCK); 8774 DELAYMS(1000); 8775 mutex_enter(&EMLXS_FCF_LOCK); 8776 } 8777 8778 if (i >= 120) { 8779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8780 "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d " 8781 "rpi_online=%d,%d. Offline timeout.", 8782 vpip->VPI, 8783 emlxs_vpi_state_xlate(vpip->state), 8784 fcfp->fcf_index, 8785 vfip->VFI, 8786 vpip->rpi_online, vpip->rpi_paused); 8787 } 8788 } 8789 8790 mutex_exit(&EMLXS_FCF_LOCK); 8791 8792 return (rval); 8793 8794 } /* emlxs_vpi_port_unbind_notify() */ 8795 8796 8797 /*ARGSUSED*/ 8798 static uint32_t 8799 emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, 8800 uint32_t evt, void *arg1) 8801 { 8802 uint32_t rval; 8803 RPIobj_t *rpip = (RPIobj_t *)arg1; 8804 8805 if (evt != FCF_EVENT_RPI_OFFLINE) { 8806 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8807 "vpi_rpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " 8808 "Invalid event type. Terminated.", 8809 vpip->VPI, 8810 emlxs_vpi_state_xlate(vpip->state), 8811 emlxs_fcf_event_xlate(evt), arg1, 8812 vpip->flag); 8813 return (1); 8814 } 8815 8816 switch (vpip->state) { 8817 case VPI_STATE_LOGO: 8818 /* rpi_online will be checked when LOGO is complete */ 8819 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8820 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " 8821 "rpi=%d. Waiting for LOGO. Terminated.", 8822 vpip->VPI, 8823 vpip->rpi_online, vpip->rpi_paused, 8824 rpip->did, rpip->RPI); 8825 8826 rval = 0; 8827 break; 8828 8829 case VPI_STATE_PORT_OFFLINE: 8830 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8831 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " 8832 "rpi=%d.", 8833 vpip->VPI, 8834 vpip->rpi_online, vpip->rpi_paused, 8835 rpip->did, rpip->RPI); 8836 8837 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 8838 FCF_REASON_REENTER, evt, arg1); 8839 break; 8840 8841 case VPI_STATE_PAUSED: 8842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8843 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " 8844 "rpi=%d. VPI paused. Terminated.", 8845 vpip->VPI, 8846 vpip->rpi_online, vpip->rpi_paused, 8847 rpip->did, rpip->RPI); 8848 8849 rval = 0; 8850 break; 8851 8852 case VPI_STATE_ONLINE: 8853 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8854 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " 8855 "rpi=%d. Terminated.", 8856 vpip->VPI, 8857 vpip->rpi_online, vpip->rpi_paused, 8858 rpip->did, rpip->RPI); 8859 8860 rval = 0; 8861 break; 8862 8863 default: 8864 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8865 "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " 8866 "rpi=%d. " 8867 "Invalid state. Terminated.", 8868 vpip->VPI, 8869 vpip->rpi_online, vpip->rpi_paused, 8870 rpip->did, rpip->RPI); 8871 8872 rval = 1; 8873 break; 8874 } 8875 8876 return (rval); 8877 8878 } /* emlxs_vpi_rpi_offline_evt_action() */ 8879 8880 8881 /*ARGSUSED*/ 8882 static uint32_t 8883 emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, 8884 uint32_t evt, void *arg1) 8885 { 8886 uint32_t rval; 8887 RPIobj_t *rpip = (RPIobj_t *)arg1; 8888 8889 if (evt != FCF_EVENT_RPI_PAUSE) { 8890 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8891 "vpi_rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " 8892 "Invalid event type. Terminated.", 8893 vpip->VPI, 8894 emlxs_vpi_state_xlate(vpip->state), 8895 emlxs_fcf_event_xlate(evt), arg1, 8896 vpip->flag); 8897 return (1); 8898 } 8899 8900 switch (vpip->state) { 8901 case VPI_STATE_LOGO: 8902 /* rpi_online will be checked when LOGO is complete */ 8903 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8904 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " 8905 "rpi=%d. Waiting for LOGO. Terminated.", 8906 vpip->VPI, 8907 vpip->rpi_online, vpip->rpi_paused, 8908 rpip->did, rpip->RPI); 8909 8910 rval = 0; 8911 break; 8912 8913 case VPI_STATE_PORT_OFFLINE: 8914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8915 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " 8916 "rpi=%d.", 8917 vpip->VPI, 8918 vpip->rpi_online, vpip->rpi_paused, 8919 rpip->did, rpip->RPI); 8920 8921 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 8922 FCF_REASON_REENTER, 0, 0); 8923 break; 8924 8925 case VPI_STATE_PAUSED: 8926 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8927 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " 8928 "rpi=%d. VPI already paused. Terminated.", 8929 vpip->VPI, 8930 vpip->rpi_online, vpip->rpi_paused, 8931 rpip->did, rpip->RPI); 8932 8933 rval = 0; 8934 break; 8935 8936 default: 8937 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8938 "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " 8939 "rpi=%d. " 8940 "Invalid state. Terminated.", 8941 vpip->VPI, 8942 vpip->rpi_online, vpip->rpi_paused, 8943 rpip->did, rpip->RPI); 8944 8945 rval = 1; 8946 break; 8947 } 8948 8949 return (rval); 8950 8951 } /* emlxs_vpi_rpi_pause_evt_action() */ 8952 8953 8954 /*ARGSUSED*/ 8955 static uint32_t 8956 emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, 8957 uint32_t evt, void *arg1) 8958 { 8959 RPIobj_t *rpip = (RPIobj_t *)arg1; 8960 8961 if (evt != FCF_EVENT_RPI_ONLINE) { 8962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8963 "vpi_rpi_online_evt_action:%d %s:%s arg=%p flag=%x. " 8964 "Invalid event type. Terminated.", 8965 vpip->VPI, 8966 emlxs_vpi_state_xlate(vpip->state), 8967 emlxs_fcf_event_xlate(evt), arg1, 8968 vpip->flag); 8969 return (1); 8970 } 8971 8972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 8973 "vpi_rpi_online_evt_action:%d rpi_online=%d,%d did=%x rpi=%d. " 8974 "Terminated.", 8975 vpip->VPI, 8976 vpip->rpi_online, vpip->rpi_paused, 8977 rpip->did, rpip->RPI); 8978 8979 return (0); 8980 8981 } /* emlxs_vpi_rpi_online_evt_action() */ 8982 8983 8984 /*ARGSUSED*/ 8985 static uint32_t 8986 emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 8987 void *arg1) 8988 { 8989 uint32_t rval; 8990 8991 if (evt != FCF_EVENT_VPI_ONLINE) { 8992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 8993 "vpi_online_evt_action:%d %s:%s arg=%p flag=%x. " 8994 "Invalid event type. Terminated.", 8995 vpip->VPI, 8996 emlxs_vpi_state_xlate(vpip->state), 8997 emlxs_fcf_event_xlate(evt), arg1, 8998 vpip->flag); 8999 return (1); 9000 } 9001 9002 if (vpip->flag & EMLXS_VPI_ONLINE_REQ) { 9003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9004 "vpi_online_evt_action:%d flag=%x. " 9005 "Online already requested. Terminated.", 9006 vpip->VPI, 9007 vpip->flag); 9008 return (1); 9009 } 9010 9011 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 9012 vpip->flag |= EMLXS_VPI_ONLINE_REQ; 9013 9014 switch (vpip->state) { 9015 case VPI_STATE_OFFLINE: 9016 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9017 "vpi_online_evt_action:%d flag=%x. Initiating online.", 9018 vpip->VPI, 9019 vpip->flag); 9020 9021 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, 9022 FCF_REASON_EVENT, evt, arg1); 9023 break; 9024 9025 case VPI_STATE_PORT_OFFLINE: 9026 case VPI_STATE_PAUSED: 9027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9028 "vpi_online_evt_action:%d flag=%x. Initiating online.", 9029 vpip->VPI, 9030 vpip->flag); 9031 9032 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, 9033 FCF_REASON_EVENT, evt, arg1); 9034 break; 9035 9036 default: 9037 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9038 "vpi_online_evt_action:%d flag=%x. Terminated.", 9039 vpip->VPI, 9040 vpip->flag); 9041 return (1); 9042 } 9043 9044 return (rval); 9045 9046 } /* emlxs_vpi_online_evt_action() */ 9047 9048 9049 /*ARGSUSED*/ 9050 static uint32_t 9051 emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1) 9052 { 9053 uint32_t rval; 9054 9055 if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) { 9056 return (0); 9057 } 9058 9059 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { 9060 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 9061 FCF_REASON_REQUESTED, 0, arg1); 9062 9063 } else if (vpip->flag & EMLXS_VPI_LOGI) { 9064 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, 9065 FCF_REASON_REQUESTED, 0, arg1); 9066 9067 } else if (vpip->flag & EMLXS_VPI_REG) { 9068 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, 9069 FCF_REASON_REQUESTED, 0, arg1); 9070 9071 } else if (vpip->flag & EMLXS_VPI_INIT) { 9072 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, 9073 FCF_REASON_REQUESTED, 0, arg1); 9074 9075 } else { 9076 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, 9077 FCF_REASON_REQUESTED, 0, arg1); 9078 } 9079 9080 return (rval); 9081 9082 } /* emlxs_vpi_offline_handler() */ 9083 9084 9085 /*ARGSUSED*/ 9086 static uint32_t 9087 emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9088 void *arg1) 9089 { 9090 uint32_t rval; 9091 uint32_t pause_req; 9092 9093 if (evt != FCF_EVENT_VPI_OFFLINE) { 9094 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9095 "vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " 9096 "Invalid event type. Terminated.", 9097 vpip->VPI, 9098 emlxs_vpi_state_xlate(vpip->state), 9099 emlxs_fcf_event_xlate(evt), arg1, 9100 vpip->flag); 9101 return (1); 9102 } 9103 9104 if ((vpip->flag & EMLXS_VPI_OFFLINE_REQ) && 9105 !(vpip->flag & EMLXS_VPI_PAUSE_REQ)) { 9106 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9107 "vpi_offline_evt_action:%d flag=%x. " 9108 "Offline already requested. Terminated.", 9109 vpip->VPI, 9110 vpip->flag); 9111 return (1); 9112 } 9113 9114 pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ; 9115 9116 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 9117 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 9118 9119 switch (vpip->state) { 9120 case VPI_STATE_PORT_OFFLINE: 9121 if (pause_req || vpip->rpi_paused) { 9122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9123 "vpi_offline_evt_action:%d flag=%x. Clear nodes.", 9124 vpip->VPI, 9125 vpip->flag); 9126 9127 vpip->flag |= EMLXS_VPI_PORT_ONLINE; 9128 9129 rval = emlxs_vpi_state(port, vpip, 9130 VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt, 9131 arg1); 9132 9133 break; 9134 } 9135 9136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9137 "vpi_offline_evt_action:%d flag=%x. Handling offline.", 9138 vpip->VPI, 9139 vpip->flag); 9140 9141 /* Handle offline now */ 9142 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9143 break; 9144 9145 case VPI_STATE_PAUSED: 9146 if (vpip->rpi_paused) { 9147 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9148 "vpi_offline_evt_action:%d flag=%x. Clear nodes.", 9149 vpip->VPI, 9150 vpip->flag); 9151 9152 vpip->flag |= EMLXS_VPI_PORT_ONLINE; 9153 9154 rval = emlxs_vpi_state(port, vpip, 9155 VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt, 9156 arg1); 9157 9158 break; 9159 } 9160 9161 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9162 "vpi_offline_evt_action:%d flag=%x. Handling offline.", 9163 vpip->VPI, 9164 vpip->flag); 9165 9166 /* Handle offline now */ 9167 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9168 break; 9169 9170 /* wait states */ 9171 case VPI_STATE_UNREG: 9172 case VPI_STATE_PORT_ONLINE: 9173 case VPI_STATE_LOGI: 9174 case VPI_STATE_INIT: 9175 case VPI_STATE_REG: 9176 case VPI_STATE_ONLINE: 9177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9178 "vpi_offline_evt_action:%d flag=%x. Handling offline.", 9179 vpip->VPI, 9180 vpip->flag); 9181 9182 /* Handle offline now */ 9183 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9184 break; 9185 9186 /* Transitional states */ 9187 default: 9188 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9189 "vpi_offline_evt_action:%d flag=%x. Terminated.", 9190 vpip->VPI, 9191 vpip->flag); 9192 break; 9193 } 9194 9195 return (rval); 9196 9197 } /* emlxs_vpi_offline_evt_action() */ 9198 9199 9200 /*ARGSUSED*/ 9201 static uint32_t 9202 emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9203 void *arg1) 9204 { 9205 emlxs_hba_t *hba = HBA; 9206 uint32_t rval; 9207 9208 if (evt != FCF_EVENT_VPI_PAUSE) { 9209 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9210 "vpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " 9211 "Invalid event type. Terminated.", 9212 vpip->VPI, 9213 emlxs_vpi_state_xlate(vpip->state), 9214 emlxs_fcf_event_xlate(evt), arg1, 9215 vpip->flag); 9216 return (1); 9217 } 9218 9219 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { 9220 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9221 "vpi_pause_evt_action:%d flag=%x. " 9222 "Pause already requested. Terminated.", 9223 vpip->VPI, 9224 vpip->flag); 9225 return (1); 9226 } 9227 9228 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 9229 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9230 "vpi_pause_evt_action:%d flag=%x. " 9231 "Offline already requested. Terminated.", 9232 vpip->VPI, 9233 vpip->flag); 9234 return (1); 9235 } 9236 9237 if (!(hba->sli.sli4.flag & EMLXS_SLI4_DOWN_LINK)) { 9238 /* Fabric logo is implied */ 9239 vpip->flag &= ~EMLXS_VPI_LOGI; 9240 if (vpip->flag & EMLXS_VPI_VFI_LOGI) { 9241 vpip->flag &= ~EMLXS_VPI_VFI_LOGI; 9242 9243 if (vpip->vfip->logi_count > 0) { 9244 vpip->vfip->logi_count--; 9245 } 9246 } 9247 } 9248 9249 switch (vpip->state) { 9250 case VPI_STATE_PORT_OFFLINE: 9251 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9252 "vpi_pause_evt_action:%d flag=%x. " 9253 "Already offline. Terminated.", 9254 vpip->VPI, 9255 vpip->flag); 9256 break; 9257 9258 case VPI_STATE_PAUSED: 9259 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9260 "vpi_pause_evt_action:%d flag=%x. " 9261 "Already paused. Terminated.", 9262 vpip->VPI, 9263 vpip->flag); 9264 break; 9265 9266 /* Wait states */ 9267 case VPI_STATE_UNREG: 9268 case VPI_STATE_PORT_ONLINE: 9269 case VPI_STATE_LOGI: 9270 case VPI_STATE_INIT: 9271 case VPI_STATE_REG: 9272 case VPI_STATE_ONLINE: 9273 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 9274 vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); 9275 9276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9277 "vpi_pause_evt_action:%d flag=%x. Handling offline.", 9278 vpip->VPI, 9279 vpip->flag); 9280 9281 /* Handle offline now */ 9282 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9283 break; 9284 9285 /* Transitional states */ 9286 default: 9287 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 9288 vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); 9289 9290 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9291 "vpi_pause_evt_action:%d flag=%x. Terminated.", 9292 vpip->VPI, 9293 vpip->flag); 9294 break; 9295 } 9296 9297 return (rval); 9298 9299 } /* emlxs_vpi_pause_evt_action() */ 9300 9301 9302 /* ARGSUSED */ 9303 static void 9304 emlxs_pkt_cmpl_thread(emlxs_hba_t *hba, 9305 void *arg1, void *arg2) 9306 { 9307 emlxs_buf_t *sbp = (emlxs_buf_t *)arg1; 9308 emlxs_pkt_complete(sbp, -1, 0, 1); 9309 9310 return; 9311 9312 } /* emlxs_pkt_cmpl_thread() */ 9313 9314 9315 /* ARGSUSED */ 9316 static void 9317 emlxs_port_offline_thread(emlxs_hba_t *hba, 9318 void *arg1, void *arg2) 9319 { 9320 emlxs_port_t *port = (emlxs_port_t *)arg1; 9321 uint32_t scope = (uint32_t)((uintptr_t)arg2); 9322 9323 (void) emlxs_port_offline(port, scope); 9324 return; 9325 9326 } /* emlxs_port_offline_thread() */ 9327 9328 9329 /* ARGSUSED */ 9330 static void 9331 emlxs_port_online_thread(emlxs_hba_t *hba, 9332 void *arg1, void *arg2) 9333 { 9334 emlxs_port_t *port = (emlxs_port_t *)arg1; 9335 9336 (void) emlxs_port_online(port); 9337 return; 9338 9339 } /* emlxs_port_online_thread() */ 9340 9341 9342 /*ARGSUSED*/ 9343 static uint32_t 9344 emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9345 void *arg1) 9346 { 9347 emlxs_hba_t *hba = HBA; 9348 uint32_t rval = 0; 9349 uint32_t scope; 9350 9351 if (vpip->state != VPI_STATE_PORT_OFFLINE) { 9352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9353 "vpi_port_offline_action:%d %s:%s arg=%p. " 9354 "Invalid state. Terminated.", 9355 vpip->VPI, 9356 emlxs_vpi_state_xlate(vpip->state), 9357 emlxs_fcf_event_xlate(evt), arg1); 9358 return (1); 9359 } 9360 9361 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { 9362 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9363 "vpi_port_offline_action:%d flag=%x. Offline port.", 9364 vpip->VPI, 9365 vpip->flag); 9366 9367 vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED); 9368 9369 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { 9370 scope = 0xFFFFFFFF; /* Clear all non-FCP2 nodes */ 9371 /* Pause FCP2 nodes */ 9372 } else { 9373 scope = 0xFDFFFFFF; /* Clear all nodes */ 9374 } 9375 9376 emlxs_thread_spawn(hba, emlxs_port_offline_thread, 9377 (void *)vpip->port, (void *)((uintptr_t)scope)); 9378 9379 if (vpip->flag & EMLXS_VPI_LOGI) { 9380 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, 9381 FCF_REASON_EVENT, evt, arg1); 9382 9383 return (rval); 9384 } 9385 } 9386 9387 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { 9388 if (vpip->rpi_online > vpip->rpi_paused) { 9389 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9390 "vpi_port_offline_action:%d rpi_online=%d,%d. " 9391 "Pausing. Waiting for RPI's.", 9392 vpip->VPI, 9393 vpip->rpi_online, vpip->rpi_paused); 9394 return (0); 9395 } 9396 9397 /* Take the Fabric RPI offline now */ 9398 if (vpip->rpip->state != RPI_STATE_FREE) { 9399 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, 9400 vpip->rpip); 9401 } 9402 9403 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9404 "vpi_port_offline_action:%d rpi_online=%d,%d. Pausing.", 9405 vpip->VPI, 9406 vpip->rpi_online, vpip->rpi_paused); 9407 9408 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED, 9409 FCF_REASON_EVENT, evt, arg1); 9410 9411 return (rval); 9412 } 9413 9414 if (vpip->rpi_online > 0) { 9415 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9416 "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. " 9417 "Waiting for RPI's.", 9418 vpip->VPI, 9419 vpip->rpi_online, vpip->rpi_paused); 9420 9421 return (0); 9422 } 9423 9424 /* Take the Fabric RPI offline now */ 9425 if (vpip->rpip->state != RPI_STATE_FREE) { 9426 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip); 9427 } 9428 9429 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9430 "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. " 9431 "Unreg VPI.", 9432 vpip->VPI, 9433 vpip->rpi_online, vpip->rpi_paused); 9434 9435 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, 9436 FCF_REASON_EVENT, evt, arg1); 9437 9438 return (rval); 9439 9440 } /* emlxs_vpi_port_offline_action() */ 9441 9442 9443 /*ARGSUSED*/ 9444 static uint32_t 9445 emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9446 void *arg1) 9447 { 9448 if (vpip->state != VPI_STATE_PAUSED) { 9449 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9450 "vpi_paused_action:%d %s:%s arg=%p. " 9451 "Invalid state. Terminated.", 9452 vpip->VPI, 9453 emlxs_vpi_state_xlate(vpip->state), 9454 emlxs_fcf_event_xlate(evt), arg1); 9455 return (1); 9456 } 9457 9458 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); 9459 9460 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9461 "vpi_paused_action:%d rpi_online=%d,%d. VPI paused.", 9462 vpip->VPI, 9463 vpip->rpi_online, vpip->rpi_paused); 9464 9465 return (0); 9466 9467 } /* emlxs_vpi_paused_action() */ 9468 9469 9470 /*ARGSUSED*/ 9471 static uint32_t 9472 emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9473 void *arg1) 9474 { 9475 uint32_t rval; 9476 9477 if (vpip->state != VPI_STATE_OFFLINE) { 9478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9479 "vpi_offline_action:%d %s:%s arg=%p. " 9480 "Invalid state. Terminated.", 9481 vpip->VPI, 9482 emlxs_vpi_state_xlate(vpip->state), 9483 emlxs_fcf_event_xlate(evt), arg1); 9484 return (1); 9485 } 9486 9487 if (!vpip->vfip) { 9488 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9489 "vpi_offline_action:%d %s:%s arg=%p flag=%x. " 9490 "Null vfip found. Terminated.", 9491 vpip->VPI, 9492 emlxs_vpi_state_xlate(vpip->state), 9493 emlxs_fcf_event_xlate(evt), arg1, 9494 vpip->flag); 9495 return (1); 9496 } 9497 9498 /* Take the Fabric RPI offline, if still active */ 9499 if (vpip->rpip->state != RPI_STATE_FREE) { 9500 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip); 9501 } 9502 9503 vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); 9504 9505 if (vpip->flag & EMLXS_VPI_VFI) { 9506 vpip->flag &= ~EMLXS_VPI_VFI; 9507 9508 if (vpip->vfip->vpi_online) { 9509 vpip->vfip->vpi_online--; 9510 } 9511 } 9512 9513 /* Check if online was requested */ 9514 if (vpip->flag & EMLXS_VPI_ONLINE_REQ) { 9515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9516 "vpi_offline_action:%d vpi_online=%d. Online requested.", 9517 vpip->VPI, 9518 vpip->vfip->vpi_online); 9519 9520 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, 9521 FCF_REASON_REQUESTED, 0, arg1); 9522 return (rval); 9523 } 9524 9525 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9526 "vpi_offline_action:%d vpi_online=%d. " 9527 "VPI offline. Notifying VFI:%d.", 9528 vpip->VPI, 9529 vpip->vfip->vpi_online, 9530 vpip->vfip->VFI); 9531 9532 /* Notify VFI */ 9533 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); 9534 9535 return (rval); 9536 9537 } /* emlxs_vpi_offline_action() */ 9538 9539 9540 /*ARGSUSED*/ 9541 static uint32_t 9542 emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 9543 { 9544 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 9545 VPIobj_t *vpip; 9546 MAILBOX4 *mb4; 9547 9548 vpip = (VPIobj_t *)mbq->context; 9549 mb4 = (MAILBOX4 *)mbq; 9550 9551 mutex_enter(&EMLXS_FCF_LOCK); 9552 9553 if (vpip->state != VPI_STATE_INIT) { 9554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9555 "vpi_init_mbcmpl:%d %s. Terminated.", 9556 vpip->VPI, 9557 emlxs_vpi_state_xlate(vpip->state)); 9558 9559 mutex_exit(&EMLXS_FCF_LOCK); 9560 return (0); 9561 } 9562 9563 if (mb4->mbxStatus) { 9564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9565 "vpi_init_mbcmpl:%d failed. status=%x", 9566 vpip->VPI, 9567 mb4->mbxStatus); 9568 9569 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED, 9570 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 9571 9572 mutex_exit(&EMLXS_FCF_LOCK); 9573 return (0); 9574 } 9575 9576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9577 "vpi_init_mbcmpl:%d Initialized.", 9578 vpip->VPI, 9579 mb4->mbxStatus); 9580 9581 vpip->flag |= EMLXS_VPI_INIT; 9582 (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL, 9583 0, 0, 0); 9584 9585 mutex_exit(&EMLXS_FCF_LOCK); 9586 return (0); 9587 9588 } /* emlxs_vpi_init_mbcmpl() */ 9589 9590 9591 /*ARGSUSED*/ 9592 static uint32_t 9593 emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9594 void *arg1) 9595 { 9596 emlxs_hba_t *hba = HBA; 9597 MAILBOXQ *mbq; 9598 MAILBOX4 *mb4; 9599 uint32_t rval; 9600 9601 if (vpip->state != VPI_STATE_INIT) { 9602 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9603 "vpi_init_action:%d %s:%s arg=%p. " 9604 "Invalid state. Terminated.", 9605 vpip->VPI, 9606 emlxs_vpi_state_xlate(vpip->state), 9607 emlxs_fcf_event_xlate(evt), arg1); 9608 return (1); 9609 } 9610 9611 if (vpip->prev_state != VPI_STATE_INIT_FAILED) { 9612 vpip->attempts = 0; 9613 } 9614 9615 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 9616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9617 "vpi_init_action:%d attempts=%d. Offline requested.", 9618 vpip->VPI, 9619 vpip->attempts); 9620 9621 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9622 return (rval); 9623 } 9624 9625 if (!(vpip->flag & EMLXS_VPI_VFI)) { 9626 vpip->flag |= EMLXS_VPI_VFI; 9627 vpip->vfip->vpi_online++; 9628 } 9629 9630 if (vpip->vfip->vpi_online == 1) { 9631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9632 "vpi_init_action:%d vpi_online=%d. Skipping init.", 9633 vpip->VPI, 9634 vpip->vfip->vpi_online); 9635 9636 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, 9637 FCF_REASON_EVENT, evt, arg1); 9638 return (rval); 9639 } 9640 9641 if (vpip->flag & EMLXS_VPI_INIT) { 9642 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9643 "vpi_init_action:%d flag=%x. " 9644 "Already init'd. Skipping init.", 9645 vpip->VPI); 9646 9647 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, 9648 FCF_REASON_EVENT, evt, arg1); 9649 return (rval); 9650 } 9651 9652 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9653 "vpi_init_action:%d vpi_online=%d attempts=%d. Sending INIT_VPI.", 9654 vpip->VPI, 9655 vpip->vfip->vpi_online, 9656 vpip->attempts); 9657 9658 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 9659 rval = emlxs_vpi_state(port, vpip, FCFI_STATE_REG_FAILED, 9660 FCF_REASON_NO_MBOX, 0, arg1); 9661 return (rval); 9662 } 9663 mb4 = (MAILBOX4*)mbq; 9664 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 9665 9666 mbq->nonembed = NULL; 9667 mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl; 9668 mbq->context = (void *)vpip; 9669 mbq->port = (void *)port; 9670 9671 mb4->mbxCommand = MBX_INIT_VPI; 9672 mb4->mbxOwner = OWN_HOST; 9673 mb4->un.varInitVPI4.vfi = vpip->vfip->VFI; 9674 mb4->un.varInitVPI4.vpi = vpip->VPI; 9675 9676 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 9677 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 9678 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 9679 9680 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED, 9681 FCF_REASON_SEND_FAILED, rval, arg1); 9682 9683 return (rval); 9684 } 9685 9686 return (0); 9687 9688 } /* emlxs_vpi_init_action() */ 9689 9690 9691 /*ARGSUSED*/ 9692 static uint32_t 9693 emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9694 void *arg1) 9695 { 9696 uint32_t rval; 9697 9698 vpip->attempts++; 9699 9700 if (vpip->state != VPI_STATE_INIT_FAILED) { 9701 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9702 "vpi_init_action:%d %s:%s arg=%p attempt=%d. " 9703 "Invalid state. Terminated.", 9704 vpip->VPI, 9705 emlxs_vpi_state_xlate(vpip->state), 9706 emlxs_fcf_event_xlate(evt), arg1, 9707 vpip->attempts); 9708 9709 return (1); 9710 } 9711 9712 if ((vpip->reason == FCF_REASON_SEND_FAILED) || 9713 (vpip->attempts >= 3)) { 9714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9715 "vpi_init_action:%d attempt=%d reason=%x. Init cmpl.", 9716 vpip->VPI, 9717 vpip->attempts, 9718 vpip->reason); 9719 9720 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); 9721 9722 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 9723 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 9724 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL, 9725 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 9726 } else { 9727 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9728 "vpi_init_action:%d attempt=%d. Initializing.", 9729 vpip->VPI, 9730 vpip->attempts); 9731 9732 rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, 9733 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 9734 } 9735 9736 return (rval); 9737 9738 } /* emlxs_vpi_init_failed_action() */ 9739 9740 9741 /*ARGSUSED*/ 9742 static uint32_t 9743 emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9744 void *arg1) 9745 { 9746 uint32_t rval; 9747 9748 if (vpip->state != VPI_STATE_INIT_CMPL) { 9749 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9750 "vpi_init_cmpl_action:%d %s:%s arg=%p. " 9751 "Invalid state. Terminated.", 9752 vpip->VPI, 9753 emlxs_vpi_state_xlate(vpip->state), 9754 emlxs_fcf_event_xlate(evt), arg1); 9755 return (1); 9756 } 9757 9758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9759 "vpi_init_cmpl_action:%d attempts=%d. Onlining port.", 9760 vpip->VPI, 9761 vpip->attempts); 9762 9763 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, 9764 FCF_REASON_EVENT, evt, arg1); 9765 return (rval); 9766 9767 } /* emlxs_vpi_init_cmpl_action() */ 9768 9769 9770 /*ARGSUSED*/ 9771 static uint32_t 9772 emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9773 void *arg1) 9774 { 9775 emlxs_hba_t *hba = HBA; 9776 uint32_t rval; 9777 9778 if (vpip->state != VPI_STATE_PORT_ONLINE) { 9779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9780 "vpi_port_online_action:%d %s:%s arg=%p. " 9781 "Invalid state. Terminated.", 9782 vpip->VPI, 9783 emlxs_vpi_state_xlate(vpip->state), 9784 emlxs_fcf_event_xlate(evt), arg1); 9785 return (1); 9786 } 9787 9788 if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { 9789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9790 "vpi_port_online_action:%d. Port already online.", 9791 vpip->VPI); 9792 } 9793 9794 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 9795 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9796 "vpi_port_online_action:%d. Offline requested.", 9797 vpip->VPI); 9798 9799 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9800 return (rval); 9801 } 9802 9803 /* Initialize the Fabric RPI */ 9804 if (vpip->rpip->state == RPI_STATE_FREE) { 9805 (void) emlxs_rpi_alloc(port, FABRIC_DID); 9806 } 9807 9808 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9809 "vpi_port_online_action:%d vpi_online=%d. Onlining port.", 9810 vpip->VPI, 9811 vpip->vfip->vpi_online); 9812 9813 /* Notify ULP */ 9814 vpip->flag |= EMLXS_VPI_PORT_ONLINE; 9815 9816 emlxs_thread_spawn(hba, emlxs_port_online_thread, 9817 (void *)vpip->port, 0); 9818 9819 /* Wait for emlxs_vpi_logi_notify() */ 9820 9821 return (0); 9822 9823 } /* emlxs_vpi_port_online_action() */ 9824 9825 9826 extern uint32_t 9827 emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp) 9828 { 9829 VPIobj_t *vpip = &port->VPIobj; 9830 emlxs_hba_t *hba = HBA; 9831 uint32_t rval; 9832 9833 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 9834 return (1); 9835 } 9836 9837 mutex_enter(&EMLXS_FCF_LOCK); 9838 9839 if (vpip->state == VPI_STATE_OFFLINE) { 9840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9841 "port_logi_notify:%d %s. Terminated.", 9842 vpip->VPI, 9843 emlxs_vpi_state_xlate(vpip->state)); 9844 9845 mutex_exit(&EMLXS_FCF_LOCK); 9846 9847 return (1); 9848 } 9849 9850 if (vpip->state != VPI_STATE_PORT_ONLINE) { 9851 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9852 "port_logi_notify:%d %s. " 9853 "Invalid state. Terminated.", 9854 vpip->VPI, 9855 emlxs_vpi_state_xlate(vpip->state)); 9856 9857 mutex_exit(&EMLXS_FCF_LOCK); 9858 9859 return (1); 9860 } 9861 9862 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI, 9863 0, 0, sbp); 9864 9865 if (rval) { 9866 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9867 "port_logi_notify:%d %s rval=%d.", 9868 vpip->VPI, 9869 emlxs_vpi_state_xlate(vpip->state), 9870 rval); 9871 } 9872 9873 mutex_exit(&EMLXS_FCF_LOCK); 9874 9875 return (rval); 9876 9877 } /* emlxs_vpi_logi_notify() */ 9878 9879 9880 extern uint32_t 9881 emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, emlxs_buf_t *sbp) 9882 { 9883 VPIobj_t *vpip = &port->VPIobj; 9884 emlxs_hba_t *hba = HBA; 9885 uint32_t rval; 9886 9887 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 9888 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 9889 IOERR_NO_RESOURCES, 1); 9890 return (1); 9891 } 9892 9893 mutex_enter(&EMLXS_FCF_LOCK); 9894 9895 if (vpip->state != VPI_STATE_LOGI) { 9896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9897 "port_logi_cmpl_notify:%d %s. " 9898 "Invalid state. Terminated.", 9899 vpip->VPI, 9900 emlxs_vpi_state_xlate(vpip->state)); 9901 9902 mutex_exit(&EMLXS_FCF_LOCK); 9903 return (1); 9904 } 9905 9906 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL, 9907 0, 0, sbp); 9908 9909 if (rval) { 9910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9911 "port_logi_cmpl_notify:%d %s rval=%d.", 9912 vpip->VPI, 9913 emlxs_vpi_state_xlate(vpip->state), 9914 rval); 9915 } 9916 9917 mutex_exit(&EMLXS_FCF_LOCK); 9918 9919 return (rval); 9920 9921 } /* emlxs_vpi_logi_cmpl_notify() */ 9922 9923 9924 extern uint32_t 9925 emlxs_vpi_logi_failed_notify(emlxs_port_t *port) 9926 { 9927 emlxs_hba_t *hba = HBA; 9928 VPIobj_t *vpip = &port->VPIobj; 9929 uint32_t rval; 9930 9931 if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { 9932 return (1); 9933 } 9934 9935 mutex_enter(&EMLXS_FCF_LOCK); 9936 9937 if (vpip->state != VPI_STATE_LOGI) { 9938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9939 "port_logi_failed_notify:%d %s. " 9940 "Invalid state. Terminated.", 9941 vpip->VPI, 9942 emlxs_vpi_state_xlate(vpip->state)); 9943 9944 mutex_exit(&EMLXS_FCF_LOCK); 9945 9946 return (1); 9947 } 9948 9949 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED, 9950 FCF_REASON_OP_FAILED, 1, 0); 9951 9952 if (rval) { 9953 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9954 "port_logi_failed_notify:%d %s rval=%d.", 9955 vpip->VPI, 9956 emlxs_vpi_state_xlate(vpip->state), 9957 rval); 9958 } 9959 9960 mutex_exit(&EMLXS_FCF_LOCK); 9961 9962 return (rval); 9963 9964 } /* emlxs_vpi_logi_failed_notify() */ 9965 9966 9967 /*ARGSUSED*/ 9968 static uint32_t 9969 emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 9970 void *arg1) 9971 { 9972 emlxs_buf_t *sbp = (emlxs_buf_t *)arg1; 9973 fc_packet_t *pkt = PRIV2PKT(sbp); 9974 uint32_t rval; 9975 9976 if (vpip->state != VPI_STATE_LOGI) { 9977 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9978 "vpi_logi_action:%d %s:%s arg=%p. " 9979 "Invalid state. Terminated.", 9980 vpip->VPI, 9981 emlxs_vpi_state_xlate(vpip->state), 9982 emlxs_fcf_event_xlate(evt), arg1); 9983 return (1); 9984 } 9985 9986 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 9987 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 9988 "vpi_logi_action:%d. Offline requested.", 9989 vpip->VPI); 9990 9991 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 9992 return (rval); 9993 } 9994 9995 if (vpip->flag & EMLXS_VPI_LOGI) { 9996 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 9997 "vpi_logi_action:%d flag=%x. LOGI already set.", 9998 vpip->VPI); 9999 10000 vpip->flag &= ~EMLXS_VPI_LOGI; 10001 if (vpip->flag & EMLXS_VPI_VFI_LOGI) { 10002 vpip->flag &= ~EMLXS_VPI_VFI_LOGI; 10003 10004 if (vpip->vfip->logi_count > 0) { 10005 vpip->vfip->logi_count--; 10006 } 10007 } 10008 } 10009 10010 /* Set login command based on vfi logi_count */ 10011 if (vpip->vfip->logi_count == 0) { 10012 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10013 "vpi_logi_action:%d logi_count=%d. FLOGI set.", 10014 vpip->VPI, 10015 vpip->vfip->logi_count); 10016 10017 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI; 10018 } else { 10019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10020 "vpi_logi_action:%d logi_count=%d. FDISC set.", 10021 vpip->VPI, 10022 vpip->vfip->logi_count); 10023 10024 *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC; 10025 } 10026 10027 vpip->vfip->logi_count++; 10028 vpip->flag |= EMLXS_VPI_VFI_LOGI; 10029 10030 return (0); 10031 10032 } /* emlxs_vpi_logi_action() */ 10033 10034 10035 /*ARGSUSED*/ 10036 static uint32_t 10037 emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10038 void *arg1) 10039 { 10040 uint32_t rval; 10041 10042 if (vpip->state != VPI_STATE_LOGI_FAILED) { 10043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10044 "vpi_logi_failed_action:%d %s:%s arg=%p. " 10045 "Invalid state. Terminated.", 10046 vpip->VPI, 10047 emlxs_vpi_state_xlate(vpip->state), 10048 emlxs_fcf_event_xlate(evt), arg1); 10049 return (1); 10050 } 10051 10052 vpip->flag &= ~EMLXS_VPI_LOGI; 10053 if (vpip->flag & EMLXS_VPI_VFI_LOGI) { 10054 vpip->flag &= ~EMLXS_VPI_VFI_LOGI; 10055 10056 if (vpip->vfip->logi_count > 0) { 10057 vpip->vfip->logi_count--; 10058 } 10059 } 10060 10061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10062 "vpi_logi_failed_action:%d. Requesting offline.", 10063 vpip->VPI); 10064 10065 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 10066 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 10067 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 10068 10069 return (rval); 10070 10071 } /* emlxs_vpi_logi_failed_action() */ 10072 10073 10074 static void 10075 emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip, uint32_t status) 10076 { 10077 emlxs_hba_t *hba = HBA; 10078 emlxs_buf_t *sbp; 10079 10080 sbp = vpip->flogi_sbp; 10081 if (!sbp) { 10082 return; 10083 } 10084 vpip->flogi_sbp = NULL; 10085 10086 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10087 "vpi_flogi_cmpl:%d. status=%x", 10088 vpip->VPI, 10089 status); 10090 10091 sbp->pkt_flags &= ~PACKET_STATE_VALID; 10092 10093 if (status) { 10094 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 10095 IOERR_NO_RESOURCES, 1); 10096 } else { 10097 emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1); 10098 } 10099 10100 emlxs_thread_spawn(hba, emlxs_pkt_cmpl_thread, (void *)sbp, 0); 10101 10102 return; 10103 10104 } /* emlxs_vpi_flogi_cmpl() */ 10105 10106 10107 /*ARGSUSED*/ 10108 static uint32_t 10109 emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10110 void *arg1) 10111 { 10112 uint32_t rval; 10113 SERV_PARM *sp; 10114 fc_packet_t *pkt; 10115 emlxs_buf_t *sbp; 10116 char buffer1[64]; 10117 char buffer2[64]; 10118 10119 if (vpip->state != VPI_STATE_LOGI_CMPL) { 10120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10121 "vpi_logi_cmpl_action:%d %s:%s arg=%p. " 10122 "Invalid state. Terminated.", 10123 vpip->VPI, 10124 emlxs_vpi_state_xlate(vpip->state), 10125 emlxs_fcf_event_xlate(evt), arg1); 10126 return (1); 10127 } 10128 10129 vpip->flag |= EMLXS_VPI_LOGI; 10130 10131 sbp = (emlxs_buf_t *)arg1; 10132 if (!sbp) { 10133 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10134 "vpi_logi_cmpl_action:%d. Null sbp. Terminated.", 10135 vpip->VPI); 10136 return (1); 10137 } 10138 10139 /* Check login parameters */ 10140 pkt = PRIV2PKT(sbp); 10141 sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t)); 10142 10143 /* For safety */ 10144 if (vpip->flogi_sbp) { 10145 emlxs_vpi_flogi_cmpl(port, vpip, 1); 10146 } 10147 vpip->flogi_sbp = sbp; 10148 10149 /* Update the Fabric RPI */ 10150 bcopy((void *)sp, (void *)&vpip->rpip->sparam, sizeof (SERV_PARM)); 10151 10152 if (vpip->vfip->vpi_online == 1) { 10153 bcopy((void *)sp, (void *)&vpip->vfip->fcf_sparam, 10154 sizeof (SERV_PARM)); 10155 } 10156 10157 if (port->prev_did && 10158 ((port->prev_did != port->did) || 10159 bcmp(&port->prev_fabric_sparam.portName, 10160 &port->fabric_sparam.portName, 8)) && 10161 emlxs_nport_count(port)) { 10162 10163 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10164 "vpi_logi_cmpl_action:%d. " 10165 "New fabric. Offlining port.", 10166 vpip->VPI); 10167 10168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10169 "vpi_logi_cmpl_action: prev_wwpn=%s wwpn=%s prev_did=%x " 10170 "did=%x.", 10171 emlxs_wwn_xlate(buffer1, 10172 (uint8_t *)&port->prev_fabric_sparam.portName), 10173 emlxs_wwn_xlate(buffer2, 10174 (uint8_t *)&port->fabric_sparam.portName), 10175 port->prev_did, port->did); 10176 10177 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 10178 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 10179 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 10180 10181 return (rval); 10182 } 10183 10184 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10185 "vpi_logi_cmpl_action:%d. Registering.", 10186 vpip->VPI); 10187 10188 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG, 10189 FCF_REASON_EVENT, evt, arg1); 10190 10191 return (rval); 10192 10193 } /* emlxs_vpi_logi_cmpl_action() */ 10194 10195 10196 /*ARGSUSED*/ 10197 static uint32_t 10198 emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10199 void *arg1) 10200 { 10201 emlxs_hba_t *hba = HBA; 10202 uint32_t rval; 10203 10204 vpip->attempts++; 10205 10206 if (vpip->state != VPI_STATE_LOGO_FAILED) { 10207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10208 "vpi_logo_failed_action:%d %s:%s arg=%p attempt=%d. " 10209 "Invalid state. Terminated.", 10210 vpip->VPI, 10211 emlxs_vpi_state_xlate(vpip->state), 10212 emlxs_fcf_event_xlate(evt), arg1, 10213 vpip->attempts); 10214 10215 return (1); 10216 } 10217 10218 if (hba->state <= FC_LINK_DOWN) { 10219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10220 "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.", 10221 vpip->VPI, 10222 vpip->attempts); 10223 10224 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, 10225 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10226 } else if (vpip->attempts >= 3) { 10227 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10228 "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.", 10229 vpip->VPI, 10230 vpip->attempts); 10231 10232 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, 10233 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10234 } else { 10235 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10236 "vpi_logo_failed_action:%d attempt=%d. Logging out.", 10237 vpip->VPI, 10238 vpip->attempts); 10239 10240 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, 10241 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10242 } 10243 10244 return (rval); 10245 10246 } /* emlxs_vpi_logo_failed_action() */ 10247 10248 10249 /*ARGSUSED*/ 10250 static uint32_t 10251 emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10252 void *arg1) 10253 { 10254 emlxs_hba_t *hba = HBA; 10255 emlxs_port_t *vport = vpip->port; 10256 uint32_t rval; 10257 uint32_t did; 10258 uint32_t sid; 10259 fc_packet_t *pkt; 10260 ELS_PKT *els; 10261 10262 if (vpip->state != VPI_STATE_LOGO) { 10263 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10264 "vpi_logo_action:%d %s:%s arg=%p. " 10265 "Invalid state. Terminated.", 10266 vpip->VPI, 10267 emlxs_vpi_state_xlate(vpip->state), 10268 emlxs_fcf_event_xlate(evt), arg1); 10269 10270 return (1); 10271 } 10272 10273 if (!(vpip->flag & EMLXS_VPI_LOGI)) { 10274 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10275 "vpi_logo_action:%d. No login. Skipping logo.", 10276 vpip->VPI); 10277 10278 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 10279 FCF_REASON_EVENT, evt, arg1); 10280 return (rval); 10281 } 10282 10283 if (!(hba->flag & FC_ONLINE_MODE)) { 10284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10285 "vpi_logo_action:%d. HBA offline. Skipping logo.", 10286 vpip->VPI); 10287 10288 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 10289 FCF_REASON_EVENT, evt, arg1); 10290 return (rval); 10291 } 10292 10293 if (vpip->prev_state != VPI_STATE_LOGO_FAILED) { 10294 vpip->attempts = 0; 10295 } 10296 10297 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10298 "vpi_logo_action:%d. Sending logo. Sending LOGO.", 10299 vpip->VPI, 10300 vpip->attempts); 10301 10302 pkt = emlxs_pkt_alloc(vport, 10303 (sizeof (uint32_t) + sizeof (LOGO)), 10304 (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP); 10305 10306 if (!pkt) { 10307 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED, 10308 FCF_REASON_NO_PKT, 0, arg1); 10309 10310 return (rval); 10311 } 10312 10313 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 10314 pkt->pkt_timeout = (2 * hba->fc_ratov); 10315 10316 /* Build the fc header */ 10317 did = FABRIC_DID; 10318 sid = (vport->did)? vport->did:vport->prev_did; 10319 10320 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 10321 pkt->pkt_cmd_fhdr.r_ctl = 10322 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 10323 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid); 10324 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 10325 pkt->pkt_cmd_fhdr.f_ctl = 10326 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 10327 pkt->pkt_cmd_fhdr.seq_id = 0; 10328 pkt->pkt_cmd_fhdr.df_ctl = 0; 10329 pkt->pkt_cmd_fhdr.seq_cnt = 0; 10330 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 10331 pkt->pkt_cmd_fhdr.rx_id = 0xffff; 10332 pkt->pkt_cmd_fhdr.ro = 0; 10333 10334 /* Build the command */ 10335 els = (ELS_PKT *)pkt->pkt_cmd; 10336 els->elsCode = 0x05; 10337 els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id; 10338 bcopy((uint8_t *)&vport->wwpn, 10339 (uint8_t *)&els->un.logo.portName, 8); 10340 10341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10342 "vpi_logo_action:%d LOGO:sid=%x did=%x.", 10343 vpip->VPI, 10344 sid, did); 10345 10346 /* Send the pkt now */ 10347 rval = emlxs_pkt_send(pkt, 1); 10348 if (rval != FC_SUCCESS) { 10349 /* Free the pkt */ 10350 emlxs_pkt_free(pkt); 10351 10352 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED, 10353 FCF_REASON_SEND_FAILED, rval, arg1); 10354 10355 return (rval); 10356 } 10357 10358 /* For now we will send and forget */ 10359 rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, 10360 FCF_REASON_EVENT, evt, arg1); 10361 10362 return (rval); 10363 10364 } /* emlxs_vpi_logo_action() */ 10365 10366 10367 /*ARGSUSED*/ 10368 static uint32_t 10369 emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10370 void *arg1) 10371 { 10372 uint32_t rval; 10373 10374 if (vpip->state != VPI_STATE_LOGO_CMPL) { 10375 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10376 "vpi_logo_cmpl_action:%d %s:%s arg=%p. " 10377 "Invalid state. Terminated.", 10378 vpip->VPI, 10379 emlxs_vpi_state_xlate(vpip->state), 10380 emlxs_fcf_event_xlate(evt), arg1); 10381 return (1); 10382 } 10383 10384 vpip->flag &= ~EMLXS_VPI_LOGI; 10385 if (vpip->flag & EMLXS_VPI_VFI_LOGI) { 10386 vpip->flag &= ~EMLXS_VPI_VFI_LOGI; 10387 10388 if (vpip->vfip->logi_count > 0) { 10389 vpip->vfip->logi_count--; 10390 } 10391 } 10392 10393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10394 "vpi_logo_cmpl_action:%d attempts=%d. Offline RPI's.", 10395 vpip->VPI, 10396 vpip->attempts); 10397 10398 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 10399 FCF_REASON_EVENT, evt, arg1); 10400 10401 return (rval); 10402 10403 } /* emlxs_vpi_logo_cmpl_action() */ 10404 10405 10406 /*ARGSUSED*/ 10407 static uint32_t 10408 emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10409 void *arg1) 10410 { 10411 uint32_t rval; 10412 10413 vpip->attempts++; 10414 10415 if (vpip->state != VPI_STATE_UNREG_FAILED) { 10416 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10417 "vpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " 10418 "Invalid state. Terminated.", 10419 vpip->VPI, 10420 emlxs_vpi_state_xlate(vpip->state), 10421 emlxs_fcf_event_xlate(evt), arg1, 10422 vpip->attempts); 10423 10424 return (1); 10425 } 10426 10427 if ((vpip->reason == FCF_REASON_SEND_FAILED) || 10428 (vpip->attempts >= 3)) { 10429 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10430 "vpi_unreg_failed_action:%d attempt=%d. Unreg cmpl.", 10431 vpip->VPI, 10432 vpip->attempts); 10433 10434 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); 10435 10436 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 10437 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 10438 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 10439 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10440 } else { 10441 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10442 "vpi_unreg_failed_action:%d attempt=%d. Unregistering.", 10443 vpip->VPI, 10444 vpip->attempts); 10445 10446 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, 10447 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10448 } 10449 10450 return (rval); 10451 10452 } /* emlxs_vpi_unreg_failed_action() */ 10453 10454 10455 /*ARGSUSED*/ 10456 static uint32_t 10457 emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 10458 { 10459 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 10460 MAILBOX4 *mb4; 10461 VPIobj_t *vpip; 10462 10463 vpip = (VPIobj_t *)mbq->context; 10464 mb4 = (MAILBOX4 *)mbq; 10465 10466 mutex_enter(&EMLXS_FCF_LOCK); 10467 10468 if (vpip->state != VPI_STATE_UNREG) { 10469 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10470 "vpi_unreg_mbcmpl:%d state=%s. Terminated.", 10471 vpip->VPI, 10472 emlxs_vpi_state_xlate(vpip->state)); 10473 10474 mutex_exit(&EMLXS_FCF_LOCK); 10475 return (0); 10476 } 10477 10478 if (mb4->mbxStatus) { 10479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10480 "vpi_unreg_mbcmpl:%d failed. status=%x", 10481 vpip->VPI, 10482 mb4->mbxStatus); 10483 10484 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, 10485 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); 10486 10487 mutex_exit(&EMLXS_FCF_LOCK); 10488 return (0); 10489 } 10490 10491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10492 "vpi_unreg_mbcmpl:%d Unregistered.", 10493 vpip->VPI); 10494 10495 vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); 10496 (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0); 10497 10498 mutex_exit(&EMLXS_FCF_LOCK); 10499 return (0); 10500 10501 } /* emlxs_vpi_unreg_mbcmpl() */ 10502 10503 10504 /*ARGSUSED*/ 10505 static uint32_t 10506 emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10507 void *arg1) 10508 { 10509 emlxs_hba_t *hba = HBA; 10510 MAILBOX4 *mb4; 10511 MAILBOXQ *mbq; 10512 uint32_t rval; 10513 10514 if (vpip->state != VPI_STATE_UNREG) { 10515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10516 "vpi_unreg_action:%d %s:%s arg=%p. " 10517 "Invalid state. Terminated.", 10518 vpip->VPI, 10519 emlxs_vpi_state_xlate(vpip->state), 10520 emlxs_fcf_event_xlate(evt), arg1); 10521 10522 return (1); 10523 } 10524 10525 if ((vpip->rpi_online > 0) || 10526 (vpip->rpip->state != RPI_STATE_FREE)) { 10527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10528 "vpi_unreg_action:%d rpi_online=%d,%d. Waiting for RPI's.", 10529 vpip->VPI, 10530 vpip->rpi_online, vpip->rpi_paused); 10531 10532 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, 10533 FCF_REASON_EVENT, evt, arg1); 10534 return (rval); 10535 } 10536 10537 if (!(vpip->flag & EMLXS_VPI_REG)) { 10538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10539 "vpi_unreg_action:%d. Not registered. Skipping unreg.", 10540 vpip->VPI); 10541 10542 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, 10543 FCF_REASON_EVENT, evt, arg1); 10544 return (rval); 10545 } 10546 10547 if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { 10548 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10549 "vpi_unreg_action:%d rpi_online=%d,%d. Pausing.", 10550 vpip->VPI, 10551 vpip->rpi_online, vpip->rpi_paused); 10552 10553 rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED, 10554 FCF_REASON_EVENT, evt, arg1); 10555 return (rval); 10556 } 10557 10558 if (vpip->prev_state != VPI_STATE_UNREG_FAILED) { 10559 vpip->attempts = 0; 10560 } 10561 10562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10563 "vpi_unreg_action:%d attempts=%d. Sending UNREG_VPI.", 10564 vpip->VPI, 10565 vpip->attempts); 10566 10567 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 10568 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, 10569 FCF_REASON_NO_MBOX, 0, arg1); 10570 10571 return (rval); 10572 } 10573 mb4 = (MAILBOX4*)mbq; 10574 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 10575 10576 mbq->nonembed = NULL; 10577 mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl; 10578 mbq->context = (void *)vpip; 10579 mbq->port = (void *)vpip->port; 10580 10581 mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */ 10582 mb4->un.varUnRegVPI4.index = vpip->VPI; 10583 mb4->mbxCommand = MBX_UNREG_VPI; 10584 mb4->mbxOwner = OWN_HOST; 10585 10586 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 10587 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 10588 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 10589 10590 rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, 10591 FCF_REASON_SEND_FAILED, rval, arg1); 10592 10593 return (rval); 10594 } 10595 10596 return (0); 10597 10598 } /* emlxs_vpi_unreg_action() */ 10599 10600 10601 /*ARGSUSED*/ 10602 static uint32_t 10603 emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10604 void *arg1) 10605 { 10606 uint32_t rval; 10607 10608 if (vpip->state != VPI_STATE_UNREG_CMPL) { 10609 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10610 "vpi_unreg_cmpl_action:%d %s:%s arg=%p. " 10611 "Invalid state. Terminated.", 10612 vpip->VPI, 10613 emlxs_vpi_state_xlate(vpip->state), 10614 emlxs_fcf_event_xlate(evt), arg1); 10615 return (1); 10616 } 10617 10618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10619 "vpi_unreg_cmpl_action:%d attempts=%d. Going offline.", 10620 vpip->VPI, 10621 vpip->attempts); 10622 10623 rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, 10624 FCF_REASON_EVENT, evt, arg1); 10625 10626 return (rval); 10627 10628 } /* emlxs_vpi_unreg_cmpl_action() */ 10629 10630 10631 /*ARGSUSED*/ 10632 static uint32_t 10633 emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10634 void *arg1) 10635 { 10636 uint32_t rval; 10637 10638 vpip->attempts++; 10639 10640 if (vpip->state != VPI_STATE_REG_FAILED) { 10641 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10642 "vpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " 10643 "Invalid state. Terminated.", 10644 vpip->VPI, 10645 emlxs_vpi_state_xlate(vpip->state), 10646 emlxs_fcf_event_xlate(evt), arg1, 10647 vpip->attempts); 10648 return (1); 10649 } 10650 10651 if ((vpip->reason == FCF_REASON_SEND_FAILED) || 10652 (vpip->attempts >= 3)) { 10653 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10654 "vpi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", 10655 vpip->VPI, 10656 vpip->attempts, 10657 vpip->reason); 10658 10659 vpip->flag &= ~EMLXS_VPI_REQ_MASK; 10660 vpip->flag |= EMLXS_VPI_OFFLINE_REQ; 10661 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL, 10662 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10663 } else { 10664 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10665 "vpi_reg_failed_action:%d attempt=%d. Registering.", 10666 vpip->VPI, 10667 vpip->attempts); 10668 10669 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG, 10670 FCF_REASON_OP_FAILED, vpip->attempts, arg1); 10671 } 10672 10673 return (rval); 10674 10675 } /* emlxs_vpi_reg_failed_action() */ 10676 10677 10678 /*ARGSUSED*/ 10679 static uint32_t 10680 emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 10681 { 10682 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 10683 MAILBOX4 *mb4; 10684 VPIobj_t *vpip; 10685 10686 vpip = (VPIobj_t *)mbq->context; 10687 mb4 = (MAILBOX4 *)mbq; 10688 10689 mutex_enter(&EMLXS_FCF_LOCK); 10690 10691 if (vpip->state != VPI_STATE_REG) { 10692 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10693 "vpi_reg_mbcmpl:%d state=%s. Terminated.", 10694 vpip->VPI, 10695 emlxs_vpi_state_xlate(vpip->state)); 10696 10697 mutex_exit(&EMLXS_FCF_LOCK); 10698 return (0); 10699 } 10700 10701 if (mb4->mbxStatus) { 10702 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10703 "vpi_reg_mbcmpl:%d failed. status=%x", 10704 vpip->VPI, 10705 mb4->mbxStatus); 10706 10707 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, 10708 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 10709 10710 mutex_exit(&EMLXS_FCF_LOCK); 10711 return (0); 10712 } 10713 10714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10715 "vpi_reg_mbcmpl:%d. Registered.", 10716 vpip->VPI); 10717 10718 vpip->flag |= EMLXS_VPI_REG; 10719 (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL, 10720 0, 0, 0); 10721 10722 mutex_exit(&EMLXS_FCF_LOCK); 10723 return (0); 10724 10725 } /* emlxs_vpi_reg_mbcmpl() */ 10726 10727 10728 /*ARGSUSED*/ 10729 static uint32_t 10730 emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10731 void *arg1) 10732 { 10733 emlxs_hba_t *hba = HBA; 10734 uint32_t *wwpn; 10735 MAILBOX *mb; 10736 MAILBOXQ *mbq; 10737 uint32_t rval; 10738 10739 if (vpip->state != VPI_STATE_REG) { 10740 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10741 "vpi_reg_action:%d %s:%s arg=%p. " 10742 "Invalid state. Terminated.", 10743 vpip->VPI, 10744 emlxs_vpi_state_xlate(vpip->state), 10745 emlxs_fcf_event_xlate(evt), arg1); 10746 return (1); 10747 } 10748 10749 if (vpip->prev_state != VPI_STATE_REG_FAILED) { 10750 vpip->attempts = 0; 10751 } 10752 10753 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 10754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10755 "vpi_reg_action:%d attempts=%d. Offline requested.", 10756 vpip->VPI, 10757 vpip->attempts); 10758 10759 rval = emlxs_vpi_offline_handler(port, vpip, 0); 10760 return (rval); 10761 } 10762 10763 if (!(vpip->flag & EMLXS_VPI_REG) && 10764 (vpip->vfip->vpi_online == 1)) { 10765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10766 "vpi_reg_action:%d. First vpi. Skipping reg.", 10767 vpip->VPI); 10768 10769 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE, 10770 FCF_REASON_EVENT, evt, arg1); 10771 10772 return (rval); 10773 } 10774 10775 if (vpip->flag & EMLXS_VPI_REG) { 10776 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10777 "vpi_reg_action:%d attempts=%d. Updating REG_VPI.", 10778 vpip->VPI, 10779 vpip->attempts); 10780 } else { 10781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10782 "vpi_reg_action:%d attempts=%d. Sending REG_VPI.", 10783 vpip->VPI, 10784 vpip->attempts); 10785 } 10786 10787 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 10788 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, 10789 FCF_REASON_NO_MBOX, 0, arg1); 10790 10791 return (rval); 10792 } 10793 mb = (MAILBOX*)mbq; 10794 bzero((void *) mb, MAILBOX_CMD_BSIZE); 10795 10796 mbq->nonembed = NULL; 10797 mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl; 10798 mbq->context = (void *)vpip; 10799 mbq->port = (void *)vpip->port; 10800 10801 mb->un.varRegVpi.vfi = vpip->vfip->VFI; 10802 mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0; 10803 10804 wwpn = (uint32_t *)&port->wwpn; 10805 mb->un.varRegVpi.portname[0] = BE_SWAP32(*wwpn); 10806 wwpn++; 10807 mb->un.varRegVpi.portname[1] = BE_SWAP32(*wwpn); 10808 10809 mb->un.varRegVpi.vpi = vpip->VPI; 10810 mb->un.varRegVpi.sid = vpip->port->did; 10811 mb->mbxCommand = MBX_REG_VPI; 10812 mb->mbxOwner = OWN_HOST; 10813 10814 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 10815 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 10816 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 10817 10818 rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, 10819 FCF_REASON_SEND_FAILED, rval, arg1); 10820 10821 return (rval); 10822 } 10823 10824 return (0); 10825 10826 } /* emlxs_vpi_reg_action() */ 10827 10828 10829 /*ARGSUSED*/ 10830 static uint32_t 10831 emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10832 void *arg1) 10833 { 10834 uint32_t rval; 10835 10836 if (vpip->state != VPI_STATE_REG_CMPL) { 10837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 10838 "vpi_reg_cmpl_action:%d %s:%s arg=%p. " 10839 "Invalid state. Terminated.", 10840 vpip->VPI, 10841 emlxs_vpi_state_xlate(vpip->state), 10842 emlxs_fcf_event_xlate(evt), arg1); 10843 return (1); 10844 } 10845 10846 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 10847 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10848 "vpi_reg_cmpl_action:%d attempts=%d. Offline requested.", 10849 vpip->VPI, 10850 vpip->attempts); 10851 10852 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 10853 return (rval); 10854 } 10855 10856 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10857 "vpi_reg_cmpl_action:%d attempts=%d. Going online.", 10858 vpip->VPI, 10859 vpip->attempts); 10860 10861 rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE, 10862 FCF_REASON_EVENT, evt, arg1); 10863 10864 return (rval); 10865 10866 } /* emlxs_vpi_reg_cmpl_action() */ 10867 10868 10869 /*ARGSUSED*/ 10870 static uint32_t 10871 emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, 10872 void *arg1) 10873 { 10874 uint32_t rval; 10875 10876 if (vpip->state != VPI_STATE_ONLINE) { 10877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10878 "vpi_online_action:%d %s:%s arg=%p. " 10879 "Invalid state. Terminated.", 10880 vpip->VPI, 10881 emlxs_vpi_state_xlate(vpip->state), 10882 emlxs_fcf_event_xlate(evt), arg1); 10883 return (1); 10884 } 10885 10886 vpip->flag &= ~EMLXS_VPI_ONLINE_REQ; 10887 10888 if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { 10889 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10890 "vpi_online_action:%d attempts=%d. Offline requested.", 10891 vpip->VPI, 10892 vpip->attempts); 10893 10894 rval = emlxs_vpi_offline_handler(port, vpip, arg1); 10895 return (rval); 10896 } 10897 10898 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 10899 "vpi_online_action:%d. VPI online. Notifying VFI:%d", 10900 vpip->VPI, 10901 vpip->vfip->VFI); 10902 10903 /* Notify VFI */ 10904 rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip); 10905 10906 return (rval); 10907 10908 } /* emlxs_vpi_online_action() */ 10909 10910 10911 /* ************************************************************************** */ 10912 /* RPI */ 10913 /* ************************************************************************** */ 10914 10915 static char * 10916 emlxs_rpi_state_xlate(uint32_t state) 10917 { 10918 static char buffer[32]; 10919 uint32_t i; 10920 uint32_t count; 10921 10922 count = sizeof (emlxs_rpi_state_table) / sizeof (emlxs_table_t); 10923 for (i = 0; i < count; i++) { 10924 if (state == emlxs_rpi_state_table[i].code) { 10925 return (emlxs_rpi_state_table[i].string); 10926 } 10927 } 10928 10929 (void) sprintf(buffer, "state=0x%x", state); 10930 return (buffer); 10931 10932 } /* emlxs_rpi_state_xlate() */ 10933 10934 10935 static uint32_t 10936 emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 10937 void *arg1) 10938 { 10939 uint32_t rval; 10940 uint32_t(*func) (emlxs_port_t *, RPIobj_t *, uint32_t, void *); 10941 uint32_t index; 10942 uint32_t events; 10943 uint16_t state; 10944 10945 /* Convert event to action table index */ 10946 switch (evt) { 10947 case FCF_EVENT_STATE_ENTER: 10948 index = 0; 10949 break; 10950 case FCF_EVENT_RPI_ONLINE: 10951 index = 1; 10952 break; 10953 case FCF_EVENT_RPI_OFFLINE: 10954 index = 2; 10955 break; 10956 case FCF_EVENT_RPI_PAUSE: 10957 index = 3; 10958 break; 10959 case FCF_EVENT_RPI_RESUME: 10960 index = 4; 10961 break; 10962 default: 10963 return (1); 10964 } 10965 10966 events = RPI_ACTION_EVENTS; 10967 state = rpip->state; 10968 10969 index += (state * events); 10970 func = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *)) 10971 emlxs_rpi_action_table[index]; 10972 10973 if (!func) { 10974 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 10975 "rpi:%d %s:%s arg=%p. No action. Terminated.", 10976 rpip->RPI, 10977 emlxs_rpi_state_xlate(rpip->state), 10978 emlxs_fcf_event_xlate(evt), arg1); 10979 10980 return (1); 10981 } 10982 10983 rval = (func)(port, rpip, evt, arg1); 10984 10985 return (rval); 10986 10987 } /* emlxs_rpi_action() */ 10988 10989 10990 static uint32_t 10991 emlxs_rpi_event(emlxs_port_t *port, uint32_t evt, 10992 void *arg1) 10993 { 10994 RPIobj_t *rpip = NULL; 10995 uint32_t rval; 10996 10997 /* Filter events and acquire fcfi context */ 10998 switch (evt) { 10999 case FCF_EVENT_RPI_ONLINE: 11000 case FCF_EVENT_RPI_OFFLINE: 11001 case FCF_EVENT_RPI_PAUSE: 11002 case FCF_EVENT_RPI_RESUME: 11003 rpip = (RPIobj_t *)arg1; 11004 11005 if (!rpip) { 11006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 11007 "rpi: %s arg=%p. Null RPI found. Terminated.", 11008 emlxs_fcf_event_xlate(evt), arg1); 11009 11010 return (1); 11011 } 11012 11013 break; 11014 11015 default: 11016 return (1); 11017 } 11018 11019 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, 11020 "rpi:%d %s:%s arg=%p", 11021 rpip->RPI, 11022 emlxs_rpi_state_xlate(rpip->state), 11023 emlxs_fcf_event_xlate(evt), arg1); 11024 11025 rval = emlxs_rpi_action(port, rpip, evt, arg1); 11026 11027 return (rval); 11028 11029 } /* emlxs_rpi_event() */ 11030 11031 11032 /*ARGSUSED*/ 11033 static uint32_t 11034 emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state, 11035 uint16_t reason, uint32_t explain, void *arg1) 11036 { 11037 uint32_t rval = 0; 11038 11039 if (state >= RPI_ACTION_STATES) { 11040 return (1); 11041 } 11042 11043 if ((rpip->state == state) && 11044 (reason != FCF_REASON_REENTER)) { 11045 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11046 "rpi_state:%d %s:%s:0x%x arg=%p. State not changed. " 11047 "Terminated.", 11048 rpip->RPI, 11049 emlxs_rpi_state_xlate(rpip->state), 11050 emlxs_fcf_reason_xlate(reason), 11051 explain, arg1); 11052 11053 return (1); 11054 } 11055 11056 if (!reason) { 11057 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 11058 "rpi:%d %s-->%s arg=%p", 11059 rpip->RPI, 11060 emlxs_rpi_state_xlate(rpip->state), 11061 emlxs_rpi_state_xlate(state), arg1); 11062 } else if (reason == FCF_REASON_EVENT) { 11063 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 11064 "rpi:%d %s-->%s:%s:%s arg=%p", 11065 rpip->RPI, 11066 emlxs_rpi_state_xlate(rpip->state), 11067 emlxs_rpi_state_xlate(state), 11068 emlxs_fcf_reason_xlate(reason), 11069 emlxs_fcf_event_xlate(explain), arg1); 11070 } else if (explain) { 11071 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 11072 "rpi:%d %s-->%s:%s:0x%x arg=%p", 11073 rpip->RPI, 11074 emlxs_rpi_state_xlate(rpip->state), 11075 emlxs_rpi_state_xlate(state), 11076 emlxs_fcf_reason_xlate(reason), 11077 explain, arg1); 11078 } else { 11079 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, 11080 "rpi:%d %s-->%s:%s arg=%p", 11081 rpip->RPI, 11082 emlxs_rpi_state_xlate(rpip->state), 11083 emlxs_rpi_state_xlate(state), 11084 emlxs_fcf_reason_xlate(reason), arg1); 11085 } 11086 11087 rpip->prev_state = rpip->state; 11088 rpip->prev_reason = rpip->reason; 11089 rpip->state = state; 11090 rpip->reason = reason; 11091 11092 rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1); 11093 11094 return (rval); 11095 11096 } /* emlxs_rpi_state() */ 11097 11098 11099 static RPIobj_t * 11100 emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did) 11101 { 11102 emlxs_hba_t *hba = HBA; 11103 uint16_t i; 11104 RPIobj_t *rpip; 11105 11106 /* Special handling for Fabric RPI */ 11107 if (did == FABRIC_DID) { 11108 /* Use the reserved RPI in the port */ 11109 rpip = &port->VPIobj.fcf_rpi; 11110 11111 bzero(rpip, sizeof (RPIobj_t)); 11112 rpip->index = 0xffff; 11113 rpip->RPI = 0xffff; 11114 rpip->did = FABRIC_DID; 11115 rpip->vpip = &port->VPIobj; 11116 11117 (void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 11118 0, 0, 0); 11119 11120 return (rpip); 11121 } 11122 11123 rpip = hba->sli.sli4.RPIp; 11124 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { 11125 /* To be consistent with SLI3, the RPI assignment */ 11126 /* starts with 1. ONLY one SLI4 HBA in the entire */ 11127 /* system will be sacrificed by one RPI and that */ 11128 /* is the one having RPI base equal 0. */ 11129 if ((rpip->state == RPI_STATE_FREE) && (rpip->RPI != 0)) { 11130 11131 bzero(rpip, sizeof (RPIobj_t)); 11132 rpip->index = i; 11133 rpip->RPI = hba->sli.sli4.RPIBase + i; 11134 rpip->vpip = &port->VPIobj; 11135 rpip->did = did; 11136 11137 (void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 11138 0, 0, 0); 11139 11140 return (rpip); 11141 } 11142 } 11143 11144 return (NULL); 11145 11146 } /* emlxs_rpi_alloc() */ 11147 11148 11149 static uint32_t 11150 emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip) 11151 { 11152 uint32_t rval; 11153 11154 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); 11155 11156 return (rval); 11157 11158 } /* emlxs_fcfi_free() */ 11159 11160 11161 extern RPIobj_t * 11162 emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi) 11163 { 11164 emlxs_hba_t *hba = HBA; 11165 RPIobj_t *rpip; 11166 11167 /* Special handling for Fabric RPI */ 11168 if (rpi == 0xffff) { 11169 return (port->VPIobj.rpip); 11170 } 11171 11172 if ((rpi < hba->sli.sli4.RPIBase) || 11173 (rpi >= hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount)) { 11174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11175 "rpi_find:%d. RPI out of range (%d,%d).", 11176 rpi, 11177 hba->sli.sli4.RPIBase, 11178 hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount); 11179 11180 return (NULL); 11181 } 11182 11183 rpip = &hba->sli.sli4.RPIp[(rpi - hba->sli.sli4.RPIBase)]; 11184 11185 if (rpip->state == RPI_STATE_FREE) { 11186 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11187 "rpi_find:%d RPI not active", 11188 rpi); 11189 11190 return (NULL); 11191 } 11192 11193 return (rpip); 11194 11195 } /* emlxs_rpi_find() */ 11196 11197 11198 static RPIobj_t * 11199 emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did) 11200 { 11201 emlxs_hba_t *hba = HBA; 11202 RPIobj_t *rpip; 11203 RPIobj_t *rpip1; 11204 uint32_t i; 11205 11206 /* Special handling for Fabric RPI */ 11207 if (did == FABRIC_DID) { 11208 return (port->VPIobj.rpip); 11209 } 11210 11211 rpip1 = NULL; 11212 rpip = hba->sli.sli4.RPIp; 11213 for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { 11214 if (rpip->state == RPI_STATE_FREE) { 11215 continue; 11216 } 11217 11218 if ((rpip->did == did) && (rpip->vpip == &port->VPIobj)) { 11219 rpip1 = rpip; 11220 break; 11221 } 11222 } 11223 11224 return (rpip1); 11225 11226 } /* emlxs_rpi_find_did() */ 11227 11228 11229 extern RPIobj_t * 11230 emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did) 11231 { 11232 emlxs_hba_t *hba = HBA; 11233 RPIobj_t *rpip; 11234 11235 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11236 return (NULL); 11237 } 11238 11239 /* Fabric RPI will be handled automatically */ 11240 if (did == FABRIC_DID) { 11241 return (NULL); 11242 } 11243 11244 mutex_enter(&EMLXS_FCF_LOCK); 11245 11246 rpip = emlxs_rpi_alloc(port, did); 11247 11248 mutex_exit(&EMLXS_FCF_LOCK); 11249 11250 return (rpip); 11251 11252 } /* emlxs_rpi_alloc_notify() */ 11253 11254 11255 extern uint32_t 11256 emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip) 11257 { 11258 emlxs_hba_t *hba = HBA; 11259 uint32_t rval; 11260 11261 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11262 return (1); 11263 } 11264 11265 if (!rpip) { 11266 return (1); 11267 } 11268 11269 /* Fabric RPI will be handled automatically */ 11270 if (rpip->did == FABRIC_DID) { 11271 return (1); 11272 } 11273 11274 mutex_enter(&EMLXS_FCF_LOCK); 11275 11276 rval = emlxs_rpi_free(port, rpip); 11277 11278 mutex_exit(&EMLXS_FCF_LOCK); 11279 11280 return (rval); 11281 11282 } /* emlxs_rpi_free_notify() */ 11283 11284 11285 extern uint32_t 11286 emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip) 11287 { 11288 emlxs_hba_t *hba = HBA; 11289 11290 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11291 return (1); 11292 } 11293 11294 if (!rpip) { 11295 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11296 "rpi_pause_notify: No RPI provided."); 11297 11298 return (1); 11299 } 11300 11301 /* Fabric RPI will be handled automatically */ 11302 if (rpip->did == FABRIC_DID) { 11303 return (1); 11304 } 11305 11306 mutex_enter(&EMLXS_FCF_LOCK); 11307 11308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11309 "rpi_pause_notify:%d %s. Pausing.", 11310 rpip->RPI, 11311 emlxs_rpi_state_xlate(rpip->state)); 11312 11313 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip); 11314 11315 mutex_exit(&EMLXS_FCF_LOCK); 11316 11317 return (0); 11318 11319 } /* emlxs_rpi_pause_notify() */ 11320 11321 11322 extern uint32_t 11323 emlxs_rpi_online_notify(emlxs_port_t *port, RPIobj_t *rpip, uint32_t did, 11324 SERV_PARM *sparam, void *arg1, void *arg2, void *arg3) 11325 { 11326 emlxs_hba_t *hba = HBA; 11327 emlxs_deferred_cmpl_t *cmpl; 11328 uint32_t allocated = 0; 11329 11330 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11331 return (1); 11332 } 11333 11334 /* Fabric RPI will be handled automatically */ 11335 if (did == FABRIC_DID) { 11336 return (1); 11337 } 11338 11339 mutex_enter(&EMLXS_FCF_LOCK); 11340 11341 if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) { 11342 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11343 "rpi_online_notify: vpi=%d. Port disabled.", 11344 port->VPIobj.VPI); 11345 11346 mutex_exit(&EMLXS_FCF_LOCK); 11347 return (1); 11348 } 11349 11350 if (!rpip) { 11351 rpip = emlxs_rpi_find_did(port, did); 11352 } 11353 11354 if (!rpip) { 11355 rpip = emlxs_rpi_alloc(port, did); 11356 allocated = 1; 11357 } 11358 11359 if (!rpip) { 11360 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11361 "rpi_online_notify: Unable to allocate an rpi. did=%x", 11362 did); 11363 11364 mutex_exit(&EMLXS_FCF_LOCK); 11365 return (1); 11366 } 11367 11368 /* Initialize RPI node info */ 11369 bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM)); 11370 11371 if (arg1 || arg2 || arg3) { 11372 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( 11373 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); 11374 11375 cmpl->port = port; 11376 cmpl->arg1 = arg1; 11377 cmpl->arg2 = arg2; 11378 cmpl->arg3 = arg3; 11379 11380 rpip->cmpl = cmpl; 11381 } 11382 11383 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11384 "rpi_online_notify:%d %s. %s. Onlining.", 11385 rpip->RPI, 11386 emlxs_rpi_state_xlate(rpip->state), 11387 ((allocated)? "Allocated":"Updated")); 11388 11389 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip); 11390 11391 if (rpip->cmpl) { 11392 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11393 "rpi_online_notify:%d %s. Deferred args not completed.", 11394 rpip->RPI, 11395 emlxs_rpi_state_xlate(rpip->state)); 11396 11397 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 11398 rpip->cmpl = 0; 11399 11400 mutex_exit(&EMLXS_FCF_LOCK); 11401 return (1); 11402 } 11403 11404 mutex_exit(&EMLXS_FCF_LOCK); 11405 11406 return (0); 11407 11408 } /* emlxs_rpi_online_notify() */ 11409 11410 11411 extern uint32_t 11412 emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip, 11413 void *arg1, void *arg2, void *arg3) 11414 { 11415 emlxs_hba_t *hba = HBA; 11416 emlxs_deferred_cmpl_t *cmpl; 11417 11418 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11419 return (1); 11420 } 11421 11422 if (!rpip) { 11423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11424 "rpi_offline_notify: No RPI provided."); 11425 11426 return (1); 11427 } 11428 11429 /* Fabric RPI will be handled automatically */ 11430 if (rpip->did == FABRIC_DID) { 11431 return (1); 11432 } 11433 11434 mutex_enter(&EMLXS_FCF_LOCK); 11435 11436 if (arg1 || arg2 || arg3) { 11437 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( 11438 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); 11439 11440 cmpl->port = port; 11441 cmpl->arg1 = arg1; 11442 cmpl->arg2 = arg2; 11443 cmpl->arg3 = arg3; 11444 11445 rpip->cmpl = cmpl; 11446 } 11447 11448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11449 "rpi_offline_notify:%d %s. Offlining.", 11450 rpip->RPI, 11451 emlxs_rpi_state_xlate(rpip->state)); 11452 11453 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip); 11454 11455 if (rpip->cmpl) { 11456 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11457 "rpi_offline_notify:%d %s. Deferred args not completed.", 11458 rpip->RPI, 11459 emlxs_rpi_state_xlate(rpip->state)); 11460 11461 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 11462 rpip->cmpl = 0; 11463 11464 mutex_exit(&EMLXS_FCF_LOCK); 11465 return (1); 11466 } 11467 11468 mutex_exit(&EMLXS_FCF_LOCK); 11469 11470 return (0); 11471 11472 } /* emlxs_rpi_offline_notify() */ 11473 11474 11475 extern uint32_t 11476 emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp) 11477 { 11478 emlxs_hba_t *hba = HBA; 11479 emlxs_deferred_cmpl_t *cmpl; 11480 11481 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 11482 return (1); 11483 } 11484 11485 if (!rpip) { 11486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11487 "rpi_resume_notify: No RPI provided."); 11488 11489 return (1); 11490 } 11491 11492 /* Fabric RPI will be handled automatically */ 11493 if (rpip->did == FABRIC_DID) { 11494 return (1); 11495 } 11496 11497 mutex_enter(&EMLXS_FCF_LOCK); 11498 11499 if (rpip->state != RPI_STATE_PAUSED) { 11500 mutex_exit(&EMLXS_FCF_LOCK); 11501 return (1); 11502 } 11503 11504 if (sbp) { 11505 cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( 11506 sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); 11507 11508 cmpl->port = port; 11509 cmpl->arg1 = (void *)sbp; 11510 cmpl->arg2 = 0; 11511 cmpl->arg3 = 0; 11512 11513 rpip->cmpl = cmpl; 11514 } 11515 11516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11517 "rpi_resume_notify:%d %s. Resuming.", 11518 rpip->RPI, 11519 emlxs_rpi_state_xlate(rpip->state)); 11520 11521 (void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip); 11522 11523 if (rpip->cmpl) { 11524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11525 "rpi_resume_notify:%d %s. Deferred args not completed.", 11526 rpip->RPI, 11527 emlxs_rpi_state_xlate(rpip->state)); 11528 11529 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 11530 rpip->cmpl = 0; 11531 11532 mutex_exit(&EMLXS_FCF_LOCK); 11533 return (1); 11534 } 11535 11536 mutex_exit(&EMLXS_FCF_LOCK); 11537 11538 return (0); 11539 11540 } /* emlxs_rpi_resume_notify() */ 11541 11542 11543 /*ARGSUSED*/ 11544 static uint32_t 11545 emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11546 void *arg1) 11547 { 11548 emlxs_hba_t *hba = HBA; 11549 XRIobj_t *xrip; 11550 XRIobj_t *next_xrip; 11551 11552 if (rpip->state != RPI_STATE_FREE) { 11553 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11554 "rpi_free_action:%d %s:%s arg=%p. " 11555 "Invalid state. Terminated.", 11556 rpip->RPI, 11557 emlxs_rpi_state_xlate(rpip->state), 11558 emlxs_fcf_event_xlate(evt), arg1); 11559 return (1); 11560 } 11561 11562 if (rpip->did == FABRIC_DID) { 11563 if (rpip->vpip->flogi_sbp) { 11564 emlxs_vpi_flogi_cmpl(port, rpip->vpip, 1); 11565 } 11566 } 11567 11568 /* Break node/RPI binding */ 11569 rw_enter(&port->node_rwlock, RW_WRITER); 11570 if (rpip->node) { 11571 rpip->node->rpip = NULL; 11572 rpip->node = NULL; 11573 } 11574 rw_exit(&port->node_rwlock); 11575 11576 /* Remove all XRIs under this RPI */ 11577 mutex_enter(&EMLXS_FCTAB_LOCK); 11578 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; 11579 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { 11580 next_xrip = xrip->_f; 11581 if (xrip->rpip == rpip) { 11582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11583 "rpi_free_action:%d xri_count=%d. " 11584 "Removing XRI:%d iotag:%d.", 11585 rpip->RPI, 11586 rpip->xri_count, 11587 xrip->XRI, xrip->iotag); 11588 11589 xrip->rpip->xri_count--; 11590 xrip->rpip = NULL; 11591 } 11592 xrip = next_xrip; 11593 } 11594 mutex_exit(&EMLXS_FCTAB_LOCK); 11595 11596 if (rpip->xri_count) { 11597 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11598 "rpi_free_action:%d. xri_count=%d", 11599 rpip->RPI, 11600 rpip->xri_count); 11601 } 11602 11603 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11604 "rpi_free_action:%d flag=%x. RPI freed.", 11605 rpip->RPI, 11606 rpip->flag); 11607 11608 rpip->flag = 0; 11609 11610 return (0); 11611 11612 } /* emlxs_rpi_free_action() */ 11613 11614 11615 /*ARGSUSED*/ 11616 static uint32_t 11617 emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11618 void *arg1) 11619 { 11620 uint32_t rval = 1; 11621 11622 if (evt != FCF_EVENT_RPI_ONLINE) { 11623 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11624 "rpi_online_evt_action:%d %s:%s arg=%p. " 11625 "Invalid event type. Terminated.", 11626 rpip->RPI, 11627 emlxs_rpi_state_xlate(rpip->state), 11628 emlxs_fcf_event_xlate(evt), arg1); 11629 return (1); 11630 } 11631 11632 switch (rpip->state) { 11633 case RPI_STATE_REG: 11634 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11635 "rpi_online_evt_action:%d flag=%x. Registering.", 11636 rpip->RPI, 11637 rpip->flag); 11638 11639 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG, 11640 FCF_REASON_REENTER, evt, arg1); 11641 break; 11642 11643 default: 11644 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11645 "rpi_online_evt_action:%d flag=%x. Registering.", 11646 rpip->RPI, 11647 rpip->flag); 11648 11649 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG, 11650 FCF_REASON_EVENT, evt, arg1); 11651 break; 11652 } 11653 11654 return (rval); 11655 11656 } /* emlxs_rpi_online_evt_action() */ 11657 11658 11659 /*ARGSUSED*/ 11660 static uint32_t 11661 emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11662 void *arg1) 11663 { 11664 uint32_t rval = 1; 11665 11666 if (evt != FCF_EVENT_RPI_OFFLINE) { 11667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11668 "rpi_offline_evt_action:%d %s:%s arg=%p. " 11669 "Invalid event type. Terminated.", 11670 rpip->RPI, 11671 emlxs_rpi_state_xlate(rpip->state), 11672 emlxs_fcf_event_xlate(evt), arg1); 11673 return (1); 11674 } 11675 11676 switch (rpip->state) { 11677 case RPI_STATE_OFFLINE: 11678 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11679 "rpi_offline_evt_action:%d flag=%x. Offlining RPI.", 11680 rpip->RPI, 11681 rpip->flag); 11682 11683 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 11684 FCF_REASON_REENTER, evt, arg1); 11685 break; 11686 11687 case RPI_STATE_UNREG: 11688 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11689 "rpi_offline_evt_action:%d flag=%x. Already unregistering. " 11690 "Terminated.", 11691 rpip->RPI, 11692 rpip->flag); 11693 11694 break; 11695 11696 default: 11697 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11698 "rpi_offline_evt_action:%d flag=%x. Unregistering.", 11699 rpip->RPI, 11700 rpip->flag); 11701 11702 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, 11703 FCF_REASON_EVENT, evt, arg1); 11704 break; 11705 11706 } 11707 11708 return (rval); 11709 11710 } /* emlxs_rpi_offline_evt_action() */ 11711 11712 11713 /*ARGSUSED*/ 11714 static uint32_t 11715 emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11716 void *arg1) 11717 { 11718 uint32_t rval = 1; 11719 11720 if (evt != FCF_EVENT_RPI_PAUSE) { 11721 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11722 "rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " 11723 "Invalid event type. Terminated.", 11724 rpip->RPI, 11725 emlxs_rpi_state_xlate(rpip->state), 11726 emlxs_fcf_event_xlate(evt), arg1, 11727 rpip->flag); 11728 return (1); 11729 } 11730 11731 switch (rpip->state) { 11732 case RPI_STATE_OFFLINE: 11733 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11734 "rpi_pause_evt_action:%d flag=%x. Offlining RPI.", 11735 rpip->RPI, 11736 rpip->flag); 11737 11738 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 11739 FCF_REASON_REENTER, evt, arg1); 11740 break; 11741 11742 case RPI_STATE_UNREG: 11743 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11744 "rpi_pause_evt_action:%d flag=%x. Not online. " 11745 "Terminated.", 11746 rpip->RPI, 11747 rpip->flag); 11748 11749 break; 11750 11751 case RPI_STATE_PAUSED: 11752 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11753 "rpi_pause_evt_action:%d flag=%x. Already paused. " 11754 "Terminated.", 11755 rpip->RPI, 11756 rpip->flag); 11757 11758 break; 11759 11760 case RPI_STATE_REG: 11761 case RPI_STATE_ONLINE: 11762 case RPI_STATE_RESUME: 11763 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11764 "rpi_pause_evt_action:%d flag=%x. Pausing.", 11765 rpip->RPI, 11766 rpip->flag); 11767 11768 rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED, 11769 FCF_REASON_EVENT, evt, arg1); 11770 break; 11771 11772 default: 11773 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11774 "rpi_pause_evt_action:%d flag=%x. Terminated.", 11775 rpip->RPI, 11776 rpip->flag); 11777 break; 11778 } 11779 11780 return (rval); 11781 11782 } /* emlxs_rpi_pause_evt_action() */ 11783 11784 11785 /*ARGSUSED*/ 11786 static uint32_t 11787 emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11788 void *arg1) 11789 { 11790 uint32_t rval = 1; 11791 11792 if (evt != FCF_EVENT_RPI_RESUME) { 11793 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11794 "rpi_resume_evt_action:%d %s:%s arg=%p flag=%x. " 11795 "Invalid event type. Terminated.", 11796 rpip->RPI, 11797 emlxs_rpi_state_xlate(rpip->state), 11798 emlxs_fcf_event_xlate(evt), arg1, 11799 rpip->flag); 11800 return (1); 11801 } 11802 11803 switch (rpip->state) { 11804 case RPI_STATE_PAUSED: 11805 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11806 "rpi_resume_evt_action:%d flag=%x. Resuming.", 11807 rpip->RPI, 11808 rpip->flag); 11809 11810 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME, 11811 FCF_REASON_EVENT, evt, arg1); 11812 break; 11813 11814 default: 11815 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11816 "rpi_resume_evt_action:%d flag=%x. Not paused. Terminated.", 11817 rpip->RPI, 11818 rpip->flag); 11819 break; 11820 } 11821 11822 return (rval); 11823 11824 } /* emlxs_rpi_resume_evt_action() */ 11825 11826 11827 /*ARGSUSED*/ 11828 static uint32_t 11829 emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11830 void *arg1) 11831 { 11832 uint32_t rval; 11833 VPIobj_t *vpip; 11834 11835 vpip = rpip->vpip; 11836 11837 if (rpip->state != RPI_STATE_OFFLINE) { 11838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11839 "rpi_offline_action:%d %s:%s arg=%p. " 11840 "Invalid state. Terminated.", 11841 rpip->RPI, 11842 emlxs_rpi_state_xlate(rpip->state), 11843 emlxs_fcf_event_xlate(evt), arg1); 11844 return (1); 11845 } 11846 11847 if (rpip->prev_state == RPI_STATE_FREE) { 11848 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11849 "rpi_offline_action:%d rpi_online=%d,%d. Terminated.", 11850 rpip->RPI, 11851 vpip->rpi_online, vpip->rpi_paused); 11852 11853 return (0); 11854 } 11855 11856 if (rpip->flag & EMLXS_RPI_PAUSED) { 11857 rpip->flag &= ~EMLXS_RPI_PAUSED; 11858 11859 if (vpip->rpi_paused) { 11860 vpip->rpi_paused--; 11861 } 11862 } 11863 11864 if (rpip->flag & EMLXS_RPI_VPI) { 11865 rpip->flag &= ~EMLXS_RPI_VPI; 11866 11867 if (vpip->rpi_online) { 11868 vpip->rpi_online--; 11869 } 11870 11871 /* Added protection */ 11872 if (vpip->rpi_online < vpip->rpi_paused) { 11873 vpip->rpi_paused = vpip->rpi_online; 11874 } 11875 } 11876 11877 if (rpip->did == FABRIC_DID) { 11878 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11879 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " 11880 "Fabric RPI offline. Freeing.", 11881 rpip->RPI, 11882 vpip->rpi_online, vpip->rpi_paused, 11883 rpip->xri_count); 11884 11885 /* Free RPI */ 11886 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); 11887 11888 return (rval); 11889 } 11890 11891 if ((vpip->rpi_online == 0) || 11892 (vpip->rpi_online == vpip->rpi_paused)) { 11893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11894 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " 11895 "RPI offline. " 11896 "Notifying VPI:%d", 11897 rpip->RPI, 11898 vpip->rpi_online, vpip->rpi_paused, 11899 rpip->xri_count, 11900 vpip->VPI); 11901 11902 /* Notify VPI */ 11903 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip); 11904 11905 } else { 11906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11907 "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " 11908 "RPI offline. Freeing.", 11909 rpip->RPI, 11910 vpip->rpi_online, vpip->rpi_paused, 11911 rpip->xri_count); 11912 } 11913 11914 /* Free RPI */ 11915 rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); 11916 11917 return (rval); 11918 11919 } /* emlxs_rpi_offline_action() */ 11920 11921 11922 /*ARGSUSED*/ 11923 static uint32_t 11924 emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11925 void *arg1) 11926 { 11927 VPIobj_t *vpip; 11928 11929 vpip = rpip->vpip; 11930 11931 if (rpip->state != RPI_STATE_PAUSED) { 11932 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11933 "rpi_paused_action:%d %s:%s arg=%p. " 11934 "Invalid state. Terminated.", 11935 rpip->RPI, 11936 emlxs_rpi_state_xlate(rpip->state), 11937 emlxs_fcf_event_xlate(evt), arg1); 11938 return (1); 11939 } 11940 11941 if (!(rpip->flag & EMLXS_RPI_PAUSED)) { 11942 rpip->flag |= EMLXS_RPI_PAUSED; 11943 vpip->rpi_paused++; 11944 } 11945 11946 /* Check if all RPI's have been paused for a VPI */ 11947 if (vpip->rpi_online == vpip->rpi_paused) { 11948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11949 "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. " 11950 "RPI paused. " 11951 "Notifying VPI:%d", 11952 rpip->RPI, 11953 vpip->rpi_online, vpip->rpi_paused, 11954 rpip->xri_count, 11955 vpip->VPI); 11956 11957 /* Notify VPI */ 11958 (void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip); 11959 11960 } else { 11961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11962 "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. " 11963 "RPI paused.", 11964 rpip->RPI, 11965 vpip->rpi_online, vpip->rpi_paused, 11966 rpip->xri_count); 11967 } 11968 11969 return (0); 11970 11971 } /* emlxs_rpi_paused_action() */ 11972 11973 11974 /*ARGSUSED*/ 11975 static uint32_t 11976 emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 11977 void *arg1) 11978 { 11979 uint32_t rval; 11980 11981 rpip->attempts++; 11982 11983 if (rpip->state != RPI_STATE_UNREG_FAILED) { 11984 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 11985 "rpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " 11986 "Invalid state. Terminated.", 11987 rpip->RPI, 11988 emlxs_rpi_state_xlate(rpip->state), 11989 emlxs_fcf_event_xlate(evt), arg1, 11990 rpip->attempts); 11991 11992 return (1); 11993 } 11994 11995 if ((rpip->reason == FCF_REASON_SEND_FAILED) || 11996 !(rpip->flag & EMLXS_RPI_REG)) { 11997 11998 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 11999 "rpi_unreg_failed_action:%d reason=%x flag=%x. " 12000 "Going offline.", 12001 rpip->RPI, 12002 rpip->reason, 12003 rpip->flag); 12004 12005 rpip->flag &= ~EMLXS_RPI_REG; 12006 12007 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12008 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12009 } else { 12010 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12011 "rpi_unreg_failed_action:%d flag=%x. Going online.", 12012 rpip->RPI, 12013 rpip->flag); 12014 12015 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12016 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12017 } 12018 12019 return (rval); 12020 12021 } /* emlxs_rpi_unreg_failed_action() */ 12022 12023 12024 static void 12025 emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip) 12026 { 12027 emlxs_hba_t *hba = HBA; 12028 VPIobj_t *vpip = rpip->vpip; 12029 emlxs_node_t *node = rpip->node; 12030 XRIobj_t *xrip; 12031 XRIobj_t *next_xrip; 12032 12033 /* Special handling for Fabric RPI */ 12034 if (rpip->did == FABRIC_DID) { 12035 if (node) { 12036 (void) emlxs_tx_node_flush(port, node, 0, 0, 0); 12037 (void) emlxs_chipq_node_flush(port, 0, node, 0); 12038 } 12039 12040 /* Clear all reserved XRIs under this RPI */ 12041 mutex_enter(&EMLXS_FCTAB_LOCK); 12042 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; 12043 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { 12044 next_xrip = xrip->_f; 12045 if ((xrip->rpip == rpip) && 12046 (xrip->flag & EMLXS_XRI_RESERVED)) { 12047 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12048 "rpi_unreg_action:%d xri_count=%d. " 12049 "Unreserving XRI:%d iotag:%d.", 12050 rpip->RPI, 12051 rpip->xri_count, 12052 xrip->XRI, xrip->iotag); 12053 12054 (void) emlxs_sli4_unreserve_xri(hba, 12055 xrip->XRI, 0); 12056 } 12057 xrip = next_xrip; 12058 } 12059 mutex_exit(&EMLXS_FCTAB_LOCK); 12060 } 12061 12062 rpip->flag &= ~EMLXS_RPI_REG; 12063 12064 if (rpip->flag & EMLXS_RPI_PAUSED) { 12065 rpip->flag &= ~EMLXS_RPI_PAUSED; 12066 12067 if (vpip->rpi_paused) { 12068 vpip->rpi_paused--; 12069 } 12070 } 12071 12072 if (rpip->flag & EMLXS_RPI_VPI) { 12073 rpip->flag &= ~EMLXS_RPI_VPI; 12074 12075 if (vpip->rpi_online) { 12076 vpip->rpi_online--; 12077 } 12078 12079 /* Added protection */ 12080 if (vpip->rpi_online < vpip->rpi_paused) { 12081 vpip->rpi_paused = vpip->rpi_online; 12082 } 12083 } 12084 12085 rw_enter(&port->node_rwlock, RW_WRITER); 12086 if (node) { 12087 rpip->node = NULL; 12088 node->rpip = NULL; 12089 } 12090 rw_exit(&port->node_rwlock); 12091 12092 if (node) { 12093 emlxs_node_rm(port, node); 12094 } 12095 12096 return; 12097 12098 } /* emlxs_rpi_unreg_handler() */ 12099 12100 12101 /*ARGSUSED*/ 12102 static uint32_t 12103 emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 12104 { 12105 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 12106 MAILBOX4 *mb4; 12107 RPIobj_t *rpip; 12108 12109 mutex_enter(&EMLXS_FCF_LOCK); 12110 12111 rpip = (RPIobj_t *)mbq->context; 12112 12113 mb4 = (MAILBOX4 *)mbq; 12114 12115 if (rpip->state != RPI_STATE_UNREG) { 12116 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12117 "rpi_unreg_mbcmpl:%d state=%s. " 12118 "No longer in RPI_STATE_UNREG. Terminated.", 12119 rpip->RPI, 12120 emlxs_rpi_state_xlate(rpip->state)); 12121 12122 mutex_exit(&EMLXS_FCF_LOCK); 12123 return (0); 12124 } 12125 12126 if (mb4->mbxStatus) { 12127 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12128 "rpi_unreg_mbcmpl:%d failed. status=%x", 12129 rpip->RPI, 12130 mb4->mbxStatus); 12131 12132 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, 12133 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 12134 12135 mutex_exit(&EMLXS_FCF_LOCK); 12136 return (0); 12137 } 12138 12139 emlxs_rpi_unreg_handler(port, rpip); 12140 12141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12142 "rpi_unreg_mbcmpl:%d Unregistered. Unreg cmpl.", 12143 rpip->RPI); 12144 12145 (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL, 12146 0, 0, 0); 12147 12148 mutex_exit(&EMLXS_FCF_LOCK); 12149 return (0); 12150 12151 } /* emlxs_rpi_unreg_mbcmpl() */ 12152 12153 12154 /*ARGSUSED*/ 12155 static uint32_t 12156 emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12157 void *arg1) 12158 { 12159 emlxs_hba_t *hba = HBA; 12160 MAILBOX4 *mb4; 12161 MAILBOXQ *mbq; 12162 uint32_t rval; 12163 VPIobj_t *vpip = rpip->vpip; 12164 12165 if (rpip->state != RPI_STATE_UNREG) { 12166 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12167 "rpi_unreg_action:%d %s:%s arg=%p. " 12168 "Invalid state. Terminated.", 12169 rpip->RPI, 12170 emlxs_rpi_state_xlate(rpip->state), 12171 emlxs_fcf_event_xlate(evt), arg1); 12172 12173 return (1); 12174 } 12175 12176 if (!(rpip->flag & EMLXS_RPI_REG)) { 12177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12178 "rpi_unreg_action:%d. Not registered. Going offline.", 12179 rpip->RPI); 12180 12181 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12182 FCF_REASON_EVENT, evt, arg1); 12183 12184 return (rval); 12185 } 12186 12187 if (rpip->prev_state != RPI_STATE_UNREG_FAILED) { 12188 rpip->attempts = 0; 12189 } 12190 12191 if (rpip->did == FABRIC_DID) { 12192 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12193 "rpi_unreg_action:%d did=%x vpi=%d. Fabric RPI. " 12194 "Going offline.", 12195 rpip->RPI, 12196 rpip->did, 12197 rpip->vpip->VPI); 12198 12199 /* Don't send UNREG_RPI, but process it as if we did */ 12200 emlxs_rpi_unreg_handler(port, rpip); 12201 12202 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12203 FCF_REASON_EVENT, evt, arg1); 12204 12205 return (rval); 12206 } 12207 12208 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12209 "rpi_unreg_action:%d attempts=%d. Sending UNREG_RPI.", 12210 rpip->RPI, 12211 rpip->attempts); 12212 12213 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 12214 12215 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, 12216 FCF_REASON_NO_MBOX, 0, arg1); 12217 12218 return (rval); 12219 } 12220 mb4 = (MAILBOX4*)mbq; 12221 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 12222 12223 mbq->nonembed = NULL; 12224 mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl; 12225 mbq->context = (void *)rpip; 12226 mbq->port = (void *)port; 12227 12228 mb4->mbxCommand = MBX_UNREG_RPI; 12229 mb4->mbxOwner = OWN_HOST; 12230 mb4->un.varUnregLogin.rpi = rpip->RPI; 12231 mb4->un.varUnregLogin.vpi = vpip->VPI; 12232 12233 if (rpip->cmpl) { 12234 mbq->sbp = rpip->cmpl->arg1; 12235 mbq->ubp = rpip->cmpl->arg2; 12236 mbq->iocbq = rpip->cmpl->arg3; 12237 } 12238 12239 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 12240 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 12241 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 12242 12243 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, 12244 FCF_REASON_SEND_FAILED, rval, arg1); 12245 12246 return (rval); 12247 } 12248 12249 if (rpip->cmpl) { 12250 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 12251 rpip->cmpl = 0; 12252 } 12253 12254 return (0); 12255 12256 } /* emlxs_rpi_unreg_action() */ 12257 12258 12259 /*ARGSUSED*/ 12260 static uint32_t 12261 emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12262 void *arg1) 12263 { 12264 uint32_t rval; 12265 12266 if (rpip->state != RPI_STATE_UNREG_CMPL) { 12267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12268 "rpi_unreg_cmpl_action:%d %s:%s arg=%p. " 12269 "Invalid state. Terminated.", 12270 rpip->RPI, 12271 emlxs_rpi_state_xlate(rpip->state), 12272 emlxs_fcf_event_xlate(evt), arg1); 12273 return (1); 12274 } 12275 12276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12277 "rpi_unreg_cmpl_action:%d flag=%x. Going offline.", 12278 rpip->RPI, 12279 rpip->flag); 12280 12281 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12282 FCF_REASON_EVENT, evt, arg1); 12283 12284 return (rval); 12285 12286 } /* emlxs_rpi_unreg_cmpl_action() */ 12287 12288 12289 /*ARGSUSED*/ 12290 static uint32_t 12291 emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12292 void *arg1) 12293 { 12294 uint32_t rval; 12295 12296 rpip->attempts++; 12297 12298 if (rpip->state != RPI_STATE_REG_FAILED) { 12299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12300 "rpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " 12301 "Invalid state. Terminated.", 12302 rpip->RPI, 12303 emlxs_rpi_state_xlate(rpip->state), 12304 emlxs_fcf_event_xlate(evt), arg1, 12305 rpip->attempts); 12306 12307 return (1); 12308 } 12309 12310 if ((rpip->reason == FCF_REASON_SEND_FAILED) || 12311 !(rpip->flag & EMLXS_RPI_REG)) { 12312 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12313 "rpi_reg_failed_action:%d reason=%x flag=%x. " 12314 "Going offline.", 12315 rpip->RPI, 12316 rpip->reason, 12317 rpip->flag); 12318 12319 rpip->flag &= ~EMLXS_RPI_REG; 12320 12321 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12322 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12323 } else { 12324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12325 "rpi_reg_failed_action:%d flag=%x. Unregistering", 12326 rpip->RPI, 12327 rpip->flag); 12328 12329 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, 12330 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12331 } 12332 12333 return (rval); 12334 12335 } /* emlxs_rpi_reg_failed_action() */ 12336 12337 12338 static uint32_t 12339 emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip) 12340 { 12341 VPIobj_t *vpip; 12342 emlxs_node_t *node; 12343 12344 vpip = rpip->vpip; 12345 12346 rpip->flag |= EMLXS_RPI_REG; 12347 12348 if (rpip->flag & EMLXS_RPI_PAUSED) { 12349 rpip->flag &= ~EMLXS_RPI_PAUSED; 12350 12351 if (vpip->rpi_paused) { 12352 vpip->rpi_paused--; 12353 } 12354 } 12355 12356 if (!(rpip->flag & EMLXS_RPI_VPI) && 12357 (rpip->did != FABRIC_DID)) { 12358 rpip->flag |= EMLXS_RPI_VPI; 12359 vpip->rpi_online++; 12360 } 12361 12362 /* Create or update the node */ 12363 node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam); 12364 12365 if (!node) { 12366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12367 "rpi_reg_handler:%d. Node create failed. Reg failed.", 12368 rpip->RPI); 12369 12370 return (FCF_REASON_NO_NODE); 12371 } 12372 12373 return (0); 12374 12375 } /* emlxs_rpi_reg_handler() */ 12376 12377 12378 /*ARGSUSED*/ 12379 static uint32_t 12380 emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 12381 { 12382 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 12383 MAILBOX4 *mb4; 12384 RPIobj_t *rpip; 12385 emlxs_node_t *node; 12386 uint32_t rval; 12387 12388 mutex_enter(&EMLXS_FCF_LOCK); 12389 12390 rpip = (RPIobj_t *)mbq->context; 12391 mb4 = (MAILBOX4 *)mbq; 12392 12393 if (rpip->state != RPI_STATE_REG) { 12394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12395 "rpi_reg_mbcmpl:%d state=%s. No longer in RPI_STATE_REG. " 12396 "Terminated.", 12397 rpip->RPI, 12398 emlxs_rpi_state_xlate(rpip->state)); 12399 12400 mutex_exit(&EMLXS_FCF_LOCK); 12401 return (0); 12402 } 12403 12404 if (mb4->mbxStatus) { 12405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12406 "rpi_reg_mbcmpl:%d failed. status=%x", 12407 rpip->RPI, 12408 mb4->mbxStatus); 12409 12410 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12411 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); 12412 12413 mutex_exit(&EMLXS_FCF_LOCK); 12414 return (0); 12415 } 12416 12417 rval = emlxs_rpi_reg_handler(port, rpip); 12418 12419 if (rval) { 12420 mb4->mbxStatus = MBX_FAILURE; 12421 12422 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12423 rval, 0, 0); 12424 12425 mutex_exit(&EMLXS_FCF_LOCK); 12426 return (0); 12427 } 12428 12429 node = rpip->node; 12430 12431 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12432 "rpi_reg_mbcmpl:%d Registered. Reg cmpl.", 12433 rpip->RPI); 12434 12435 (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0); 12436 12437 mutex_exit(&EMLXS_FCF_LOCK); 12438 12439 /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */ 12440 if (mbq->sbp) { 12441 ((emlxs_buf_t *)mbq->sbp)->node = node; 12442 } 12443 12444 #ifdef DHCHAP_SUPPORT 12445 if (mbq->sbp || mbq->ubp) { 12446 if (emlxs_dhc_auth_start(port, node, (uint8_t *)mbq->sbp, 12447 (uint8_t *)mbq->ubp) == 0) { 12448 /* Auth started - auth completion will */ 12449 /* handle sbp and ubp now */ 12450 mbq->sbp = NULL; 12451 mbq->ubp = NULL; 12452 } 12453 } 12454 #endif /* DHCHAP_SUPPORT */ 12455 12456 return (0); 12457 12458 } /* emlxs_rpi_reg_mbcmpl() */ 12459 12460 12461 /*ARGSUSED*/ 12462 static uint32_t 12463 emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12464 void *arg1) 12465 { 12466 emlxs_hba_t *hba = HBA; 12467 MAILBOX4 *mb4; 12468 MAILBOXQ *mbq; 12469 MATCHMAP *mp; 12470 uint32_t rval; 12471 12472 if (rpip->state != RPI_STATE_REG) { 12473 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12474 "rpi_reg_action:%d %s:%s arg=%p. " 12475 "Invalid state. Terminated.", 12476 rpip->RPI, 12477 emlxs_rpi_state_xlate(rpip->state), 12478 emlxs_fcf_event_xlate(evt), arg1); 12479 12480 return (1); 12481 } 12482 12483 if (rpip->did == FABRIC_DID) { 12484 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12485 "rpi_reg_action:%d did=%x vpi=%d. Fabric RPI. " 12486 "Going online.", 12487 rpip->RPI, 12488 rpip->did, 12489 rpip->vpip->VPI); 12490 12491 /* Don't send REG_RPI, but process it as if we did */ 12492 rval = emlxs_rpi_reg_handler(port, rpip); 12493 12494 if (rval) { 12495 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12496 rval, 0, 0); 12497 12498 return (rval); 12499 } 12500 12501 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12502 FCF_REASON_EVENT, evt, arg1); 12503 12504 return (rval); 12505 } 12506 12507 if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) { 12508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12509 "rpi_reg_action:%d did=%x. vpi=%d. Port disabled. " 12510 "Offlining RPI.", 12511 rpip->RPI, 12512 rpip->did, 12513 rpip->vpip->VPI); 12514 12515 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12516 FCF_REASON_NOT_ALLOWED, evt, arg1); 12517 12518 return (rval); 12519 } 12520 12521 if (rpip->prev_state != RPI_STATE_REG_FAILED) { 12522 rpip->attempts = 0; 12523 } 12524 12525 if (rpip->flag & EMLXS_RPI_REG) { 12526 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12527 "rpi_reg_action:%d flag=%x. Already registered. " 12528 "Updating registration.", 12529 rpip->RPI, rpip->flag); 12530 } 12531 12532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12533 "rpi_reg_action:%d attempts=%d. Sending REG_RPI.", 12534 rpip->RPI, 12535 rpip->attempts); 12536 12537 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 12538 12539 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12540 FCF_REASON_NO_MBOX, 0, arg1); 12541 12542 return (rval); 12543 } 12544 12545 mb4 = (MAILBOX4*)mbq; 12546 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 12547 12548 if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { 12549 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 12550 12551 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12552 FCF_REASON_NO_BUFFER, 0, arg1); 12553 12554 return (rval); 12555 } 12556 12557 mbq->bp = (void *)mp; 12558 mbq->nonembed = NULL; 12559 12560 mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl; 12561 mbq->context = (void *)rpip; 12562 mbq->port = (void *)port; 12563 12564 mb4->mbxCommand = MBX_REG_RPI; 12565 mb4->mbxOwner = OWN_HOST; 12566 12567 mb4->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 12568 mb4->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys); 12569 mb4->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys); 12570 mb4->un.varRegLogin.did = rpip->did; 12571 mb4->un.varWords[30] = 0; /* flags */ 12572 12573 mb4->un.varRegLogin.vpi = rpip->vpip->VPI; 12574 mb4->un.varRegLogin.rpi = rpip->RPI; 12575 12576 bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM)); 12577 12578 if (rpip->cmpl) { 12579 mbq->sbp = rpip->cmpl->arg1; 12580 mbq->ubp = rpip->cmpl->arg2; 12581 mbq->iocbq = rpip->cmpl->arg3; 12582 } 12583 12584 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 12585 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 12586 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 12587 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 12588 12589 rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, 12590 FCF_REASON_SEND_FAILED, rval, arg1); 12591 12592 return (rval); 12593 } 12594 12595 if (rpip->cmpl) { 12596 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 12597 rpip->cmpl = 0; 12598 } 12599 12600 return (0); 12601 12602 } /* emlxs_rpi_reg_action() */ 12603 12604 12605 /*ARGSUSED*/ 12606 static uint32_t 12607 emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12608 void *arg1) 12609 { 12610 uint32_t rval; 12611 12612 if (rpip->state != RPI_STATE_REG_CMPL) { 12613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12614 "rpi_reg_cmpl_action:%d %s:%s arg=%p. " 12615 "Invalid state. Terminated.", 12616 rpip->RPI, 12617 emlxs_rpi_state_xlate(rpip->state), 12618 emlxs_fcf_event_xlate(evt), arg1); 12619 return (1); 12620 } 12621 12622 if (rpip->flag & EMLXS_RPI_REG) { 12623 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12624 "rpi_reg_cmpl_action:%d flag=%x. Going online", 12625 rpip->RPI, 12626 rpip->flag); 12627 12628 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12629 FCF_REASON_EVENT, evt, arg1); 12630 } else { 12631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12632 "rpi_reg_cmpl_action:%d flag=%x. Going offline.", 12633 rpip->RPI, 12634 rpip->flag); 12635 12636 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12637 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12638 } 12639 12640 return (rval); 12641 12642 } /* emlxs_rpi_reg_cmpl_action() */ 12643 12644 12645 /*ARGSUSED*/ 12646 static uint32_t 12647 emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip, 12648 uint32_t evt, void *arg1) 12649 { 12650 uint32_t rval; 12651 12652 rpip->attempts++; 12653 12654 if (rpip->state != RPI_STATE_RESUME_FAILED) { 12655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12656 "rpi_resume_failed_action:%d %s:%s arg=%p attempt=%d. " 12657 "Invalid state. Terminated.", 12658 rpip->RPI, 12659 emlxs_rpi_state_xlate(rpip->state), 12660 emlxs_fcf_event_xlate(evt), arg1, 12661 rpip->attempts); 12662 12663 return (1); 12664 } 12665 12666 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12667 "rpi_resume_failed_action:%d attempt=%d. Unregistering.", 12668 rpip->RPI, 12669 rpip->attempts); 12670 12671 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, 12672 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12673 12674 return (rval); 12675 12676 } /* emlxs_rpi_resume_failed_action() */ 12677 12678 12679 /*ARGSUSED*/ 12680 static void 12681 emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip) 12682 { 12683 if (rpip->flag & EMLXS_RPI_PAUSED) { 12684 rpip->flag &= ~EMLXS_RPI_PAUSED; 12685 12686 if (rpip->vpip->rpi_paused) { 12687 rpip->vpip->rpi_paused--; 12688 } 12689 } 12690 12691 return; 12692 12693 } /* emlxs_rpi_resume_handler() */ 12694 12695 12696 /*ARGSUSED*/ 12697 static uint32_t 12698 emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 12699 { 12700 emlxs_port_t *port = (emlxs_port_t *)mbq->port; 12701 MAILBOX4 *mb4; 12702 RPIobj_t *rpip; 12703 12704 mutex_enter(&EMLXS_FCF_LOCK); 12705 12706 rpip = (RPIobj_t *)mbq->context; 12707 mb4 = (MAILBOX4 *)mbq; 12708 12709 if (rpip->state != RPI_STATE_RESUME) { 12710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12711 "rpi_resume_mbcmpl:%d state=%s. " 12712 "No longer in RPI_STATE_RESUME. Terminated.", 12713 rpip->RPI, 12714 emlxs_rpi_state_xlate(rpip->state)); 12715 12716 mutex_exit(&EMLXS_FCF_LOCK); 12717 return (0); 12718 } 12719 12720 if (mb4->mbxStatus) { 12721 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12722 "rpi_resume_mbcmpl:%d failed. status=%x", 12723 rpip->RPI, 12724 mb4->mbxStatus); 12725 12726 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, 12727 FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); 12728 12729 mutex_exit(&EMLXS_FCF_LOCK); 12730 return (0); 12731 } 12732 12733 emlxs_rpi_resume_handler(port, rpip); 12734 12735 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12736 "rpi_resume_mbcmpl:%d Resumed. Resume cmpl.", 12737 rpip->RPI); 12738 12739 (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0); 12740 12741 mutex_exit(&EMLXS_FCF_LOCK); 12742 12743 return (0); 12744 12745 } /* emlxs_rpi_resume_mbcmpl() */ 12746 12747 12748 /*ARGSUSED*/ 12749 static uint32_t 12750 emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12751 void *arg1) 12752 { 12753 emlxs_hba_t *hba = HBA; 12754 MAILBOX4 *mb4; 12755 MAILBOXQ *mbq; 12756 uint32_t rval; 12757 12758 if (rpip->state != RPI_STATE_RESUME) { 12759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12760 "rpi_resume_action:%d %s:%s arg=%p. " 12761 "Invalid state. Terminated.", 12762 rpip->RPI, 12763 emlxs_rpi_state_xlate(rpip->state), 12764 emlxs_fcf_event_xlate(evt), arg1); 12765 12766 return (1); 12767 } 12768 12769 if (!(rpip->flag & EMLXS_RPI_PAUSED)) { 12770 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12771 "rpi_resume_action:%d flag=%x. Not Paused. Going online.", 12772 rpip->RPI, rpip->flag); 12773 12774 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12775 FCF_REASON_EVENT, evt, arg1); 12776 12777 return (rval); 12778 } 12779 12780 if (rpip->did == FABRIC_DID) { 12781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12782 "rpi_resume_action:%d. Fabric RPI. " 12783 "Going online.", 12784 rpip->RPI); 12785 12786 /* Don't send RESUME_RPI, but process it as if we did */ 12787 emlxs_rpi_resume_handler(port, rpip); 12788 12789 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12790 FCF_REASON_EVENT, evt, arg1); 12791 12792 return (rval); 12793 } 12794 12795 if (rpip->prev_state != RPI_STATE_RESUME_FAILED) { 12796 rpip->attempts = 0; 12797 } 12798 12799 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12800 "rpi_resume_action:%d attempts=%d. Sending RESUME_RPI.", 12801 rpip->RPI, 12802 rpip->attempts); 12803 12804 if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 12805 12806 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, 12807 FCF_REASON_NO_MBOX, 0, arg1); 12808 12809 return (rval); 12810 } 12811 mb4 = (MAILBOX4*)mbq; 12812 bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); 12813 12814 mbq->nonembed = NULL; 12815 mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl; 12816 mbq->context = (void *)rpip; 12817 mbq->port = (void *)port; 12818 12819 mb4->mbxCommand = MBX_RESUME_RPI; 12820 mb4->mbxOwner = OWN_HOST; 12821 12822 mb4->un.varResumeRPI.EventTag = hba->link_event_tag; 12823 mb4->un.varResumeRPI.RPI = rpip->RPI; 12824 12825 if (rpip->cmpl) { 12826 mbq->sbp = rpip->cmpl->arg1; 12827 mbq->ubp = rpip->cmpl->arg2; 12828 mbq->iocbq = rpip->cmpl->arg3; 12829 } 12830 12831 rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 12832 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 12833 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 12834 12835 rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, 12836 FCF_REASON_SEND_FAILED, rval, arg1); 12837 12838 return (rval); 12839 } 12840 12841 if (rpip->cmpl) { 12842 kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); 12843 rpip->cmpl = 0; 12844 } 12845 12846 return (0); 12847 12848 } /* emlxs_rpi_resume_action() */ 12849 12850 12851 static uint32_t 12852 emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12853 void *arg1) 12854 { 12855 uint32_t rval; 12856 12857 if (rpip->state != RPI_STATE_RESUME_CMPL) { 12858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, 12859 "rpi_resume_cmpl_action:%d %s:%s arg=%p. " 12860 "Invalid state. Terminated.", 12861 rpip->RPI, 12862 emlxs_rpi_state_xlate(rpip->state), 12863 emlxs_fcf_event_xlate(evt), arg1); 12864 return (1); 12865 } 12866 12867 if (rpip->flag & EMLXS_RPI_PAUSED) { 12868 if (rpip->flag & EMLXS_RPI_REG) { 12869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12870 "rpi_reg_cmpl_action:%d flag=%x. Unregistering.", 12871 rpip->RPI, 12872 rpip->flag); 12873 12874 rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, 12875 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12876 } else { 12877 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12878 "rpi_reg_cmpl_action:%d flag=%x. Going offline.", 12879 rpip->RPI, 12880 rpip->flag); 12881 12882 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12883 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12884 } 12885 } else { 12886 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12887 "rpi_resume_cmpl_action:%d flag=%x. Going online.", 12888 rpip->RPI, 12889 rpip->flag); 12890 12891 rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, 12892 FCF_REASON_OP_FAILED, rpip->attempts, arg1); 12893 } 12894 12895 return (rval); 12896 12897 } /* emlxs_rpi_resume_cmpl_action() */ 12898 12899 12900 /*ARGSUSED*/ 12901 static uint32_t 12902 emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, 12903 void *arg1) 12904 { 12905 emlxs_hba_t *hba = HBA; 12906 uint32_t rval; 12907 12908 if (rpip->state != RPI_STATE_ONLINE) { 12909 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12910 "rpi_online_action:%d %s:%s arg=%p. " 12911 "Invalid state. Terminated.", 12912 rpip->RPI, 12913 emlxs_rpi_state_xlate(rpip->state), 12914 emlxs_fcf_event_xlate(evt), arg1); 12915 return (1); 12916 } 12917 12918 if (rpip->did == FABRIC_DID) { 12919 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12920 "rpi_online_action:%d did=%x. Fabric RPI online. " 12921 "Terminated.", 12922 rpip->RPI, 12923 rpip->did, 12924 rpip->vpip->VPI); 12925 12926 EMLXS_STATE_CHANGE(hba, FC_READY); 12927 12928 if (rpip->vpip->flogi_sbp) { 12929 emlxs_vpi_flogi_cmpl(port, rpip->vpip, 0); 12930 } 12931 12932 return (0); 12933 } 12934 12935 if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) { 12936 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12937 "rpi_online_action:%d did=%x. vpi=%d. Port disabled. " 12938 "Offlining RPI.", 12939 rpip->RPI, 12940 rpip->did, 12941 rpip->vpip->VPI); 12942 12943 rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, 12944 FCF_REASON_NOT_ALLOWED, evt, arg1); 12945 12946 return (rval); 12947 } 12948 12949 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, 12950 "rpi_online_action:%d did=%x. RPI online. Notifying VPI:%d.", 12951 rpip->RPI, 12952 rpip->did, 12953 rpip->vpip->VPI); 12954 12955 /* Notify VPI */ 12956 rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip); 12957 12958 return (rval); 12959 12960 } /* emlxs_rpi_online_action() */ 12961