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 9 * http://www.opensource.org/licenses/cddl1.txt. 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 (c) 2004-2012 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <emlxs.h> 28 29 #ifdef SFCT_SUPPORT 30 31 32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33 EMLXS_MSG_DEF(EMLXS_FCT_C); 34 35 static void emlxs_fct_memseg_init(emlxs_hba_t *hba); 36 37 static fct_status_t emlxs_fct_cmd_acquire(emlxs_port_t *port, 38 fct_cmd_t *fct_cmd, uint16_t fct_state); 39 static fct_status_t emlxs_fct_cmd_accept(emlxs_port_t *port, 40 fct_cmd_t *fct_cmd, uint16_t fct_state); 41 static void emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd, 42 uint16_t fct_state); 43 44 static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port, 45 fct_cmd_t *fct_cmd, uint16_t fct_state); 46 static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, 47 uint16_t fct_state); 48 static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd, 49 uint16_t fct_state); 50 51 static fct_status_t emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, 52 struct fct_flogi_xchg *fx); 53 static fct_status_t emlxs_fct_get_link_info(fct_local_port_t *fct_port, 54 fct_link_info_t *link); 55 static fct_status_t emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port, 56 fct_remote_port_t *port_handle); 57 static fct_status_t emlxs_fct_send_cmd(fct_cmd_t *fct_cmd); 58 static fct_status_t emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, 59 stmf_data_buf_t *dbuf, uint32_t ioflags); 60 static fct_status_t emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t flags); 61 static fct_status_t emlxs_fct_abort(fct_local_port_t *fct_port, 62 fct_cmd_t *cmd, uint32_t flags); 63 static void emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg); 64 static fct_status_t emlxs_fct_register_remote_port(fct_local_port_t *fct_port, 65 fct_remote_port_t *port_handle, fct_cmd_t *plogi); 66 static fct_status_t emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd); 67 static fct_status_t emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd); 68 static fct_status_t emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd); 69 static fct_status_t emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd); 70 static void emlxs_fct_pkt_comp(fc_packet_t *pkt); 71 static void emlxs_fct_populate_hba_details(fct_local_port_t *fct_port, 72 fct_port_attrs_t *port_attrs); 73 static fct_status_t emlxs_fct_port_info(uint32_t cmd, 74 fct_local_port_t *fct_port, void *arg, uint8_t *buffer, uint32_t *size); 75 76 static fct_status_t emlxs_fct_dmem_init(emlxs_port_t *port); 77 static void emlxs_fct_dmem_fini(emlxs_port_t *port); 78 79 static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, 80 uint32_t size, uint32_t *pminsize, uint32_t flags); 81 static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf); 82 83 static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf, 84 uint_t sync_type); 85 static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port, 86 fct_cmd_t *fct_cmd, fc_packet_t *pkt); 87 88 static void emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1, 89 void *arg2); 90 static void emlxs_fct_unsol_flush(emlxs_port_t *port); 91 static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port, 92 CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); 93 static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port, 94 CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); 95 static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port, 96 emlxs_buf_t *cmd_sbp); 97 static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port, 98 emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd); 99 100 #ifdef FCT_IO_TRACE 101 uint8_t *emlxs_iotrace = 0; /* global for mdb */ 102 int emlxs_iotrace_cnt = 0; 103 104 /* 105 * 106 * FCT_CMD (cmd_sbp->fct_state) 107 * 108 * STATE LOCK STATUS OWNER 109 * ----------------------------------------------------------------------------- 110 * EMLXS_FCT_ABORT_DONE Lock Destroyed COMSTAR 111 * EMLXS_FCT_IO_DONE Lock Destroyed COMSTAR 112 * 113 * EMLXS_FCT_CMD_POSTED Lock Released COMSTAR 114 * EMLXS_FCT_OWNED Lock Released COMSTAR 115 * 116 * EMLXS_FCT_CMD_WAITQ Lock Released DRIVER 117 * EMLXS_FCT_RSP_PENDING Lock Released DRIVER 118 * EMLXS_FCT_REQ_PENDING Lock Released DRIVER 119 * EMLXS_FCT_REG_PENDING Lock Released DRIVER 120 * EMLXS_FCT_DATA_PENDING Lock Released DRIVER 121 * EMLXS_FCT_STATUS_PENDING Lock Released DRIVER 122 * EMLXS_FCT_CLOSE_PENDING Lock Released DRIVER 123 * EMLXS_FCT_ABORT_PENDING Lock Released DRIVER 124 * 125 * EMLXS_FCT_FCP_CMD_RECEIVED Transistional, lock held DRIVER 126 * EMLXS_FCT_ELS_CMD_RECEIVED Transistional, lock held DRIVER 127 * EMLXS_FCT_SEND_CMD_RSP Transistional, lock held DRIVER 128 * EMLXS_FCT_SEND_ELS_RSP Transistional, lock held DRIVER 129 * EMLXS_FCT_SEND_ELS_REQ Transistional, lock held DRIVER 130 * EMLXS_FCT_SEND_CT_REQ Transistional, lock held DRIVER 131 * EMLXS_FCT_REG_COMPLETE Transistional, lock held DRIVER 132 * EMLXS_FCT_SEND_FCP_DATA Transistional, lock held DRIVER 133 * EMLXS_FCT_SEND_FCP_STATUS Transistional, lock held DRIVER 134 * EMLXS_FCT_PKT_COMPLETE Transistional, lock held DRIVER 135 * EMLXS_FCT_PKT_FCPRSP_COMPLETE Transistional, lock held DRIVER 136 * EMLXS_FCT_PKT_ELSRSP_COMPLETE Transistional, lock held DRIVER 137 * EMLXS_FCT_PKT_ELSCMD_COMPLETE Transistional, lock held DRIVER 138 * EMLXS_FCT_PKT_CTCMD_COMPLETE Transistional, lock held DRIVER 139 * EMLXS_FCT_REQ_COMPLETE Transistional, lock held DRIVER 140 * 141 * 142 * COMSTAR OWNED DRIVER OWNED 143 * ------------- --------------------------------------------------- 144 * ------- > @ Accept---- >Release @ Acquire--- >+ 145 * | 146 * < ------- @ Post/Done< ----Acquire @ Release< ---+ 147 * 148 * @ :Indicates COMSTAR use of emlxs_fct_abort() 149 * Abort requests set the EMLXS_FCT_ABORT_INP flag. 150 * 151 * Accept :Indicates use of emlxs_fct_cmd_accept() 152 * Acquire :Indicates use of emlxs_fct_cmd_acquire() 153 * Post :Indicates use of emlxs_fct_cmd_post() 154 * Done :Indicates use of emlxs_fct_cmd_done() 155 */ 156 157 void 158 emlxs_fct_io_trace(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t data) 159 { 160 emlxs_iotrace_t *iop = port->iotrace; 161 uint16_t iotrace_cnt; 162 uint16_t iotrace_index; 163 int i; 164 165 if (!iop) { 166 return; 167 } 168 169 mutex_enter(&port->iotrace_mtx); 170 iotrace_cnt = port->iotrace_cnt; 171 iotrace_index = port->iotrace_index; 172 173 switch (data) { 174 175 /* New entry */ 176 case EMLXS_FCT_ELS_CMD_RECEIVED: 177 case EMLXS_FCT_FCP_CMD_RECEIVED: 178 case EMLXS_FCT_SEND_ELS_REQ: 179 case EMLXS_FCT_SEND_CT_REQ: 180 for (i = 0; i < iotrace_cnt; i++) { 181 if ((iop->fct_cmd == fct_cmd) && 182 (iop->trc[0] != (uint8_t)(0))) 183 break; 184 iop++; 185 } 186 if (i < iotrace_cnt) { 187 /* New entry already exists */ 188 mutex_exit(&port->iotrace_mtx); 189 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 190 "IOTRACE: New entry already exists: fct_cmd: %p", 191 fct_cmd); 192 return; 193 } 194 iop = port->iotrace + iotrace_index; 195 for (i = 0; i < iotrace_cnt; i++) { 196 if (iop->trc[0] == (uint8_t)(0)) 197 break; 198 199 iop++; 200 if (iop == (port->iotrace + iotrace_cnt)) 201 iop = port->iotrace; 202 } 203 if (i >= iotrace_cnt) { 204 /* No new slots available */ 205 mutex_exit(&port->iotrace_mtx); 206 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 207 "IOTRACE: No new slots: fct_cmd: %p data: %d", 208 fct_cmd, data); 209 return; 210 } 211 port->iotrace_index++; 212 if (port->iotrace_index >= iotrace_cnt) 213 port->iotrace_index = 0; 214 215 bzero((uint8_t *)iop, sizeof (emlxs_iotrace_t)); 216 iop->fct_cmd = fct_cmd; 217 iop->xri = fct_cmd->cmd_rxid; 218 iop->marker = 0xff; 219 iop->trc[0] = 2; 220 iop->trc[1] = data; 221 mutex_exit(&port->iotrace_mtx); 222 return; 223 } 224 225 for (i = 0; i < iotrace_cnt; i++) { 226 if ((iop->fct_cmd == fct_cmd) && 227 (iop->trc[0] != (uint8_t)(0))) 228 break; 229 iop++; 230 } 231 if (i >= iotrace_cnt) { 232 /* Cannot find existing slot for fct_cmd */ 233 mutex_exit(&port->iotrace_mtx); 234 235 if ((data != EMLXS_FCT_REG_PENDING) && 236 (data != EMLXS_FCT_REG_COMPLETE)) { 237 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 238 "IOTRACE: Missing slot: fct_cmd: %p data: %d", 239 fct_cmd, data); 240 } 241 return; 242 } 243 244 if (iop->trc[0] >= MAX_IO_TRACE) { 245 /* trc overrun for fct_cmd */ 246 mutex_exit(&port->iotrace_mtx); 247 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 248 "IOTRACE: trc overrun slot: fct_cmd: %p data: %d", 249 fct_cmd, data); 250 return; 251 } 252 253 if (iop->xri != fct_cmd->cmd_rxid) { 254 /* xri mismatch for fct_cmd */ 255 mutex_exit(&port->iotrace_mtx); 256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 257 "IOTRACE: xri mismatch %x != %x: fct_cmd: %p data: %d", 258 iop->xri, fct_cmd->cmd_rxid, fct_cmd, data); 259 return; 260 } 261 262 iop->trc[iop->trc[0]] = data; 263 if ((data == EMLXS_FCT_IO_DONE) || (data == EMLXS_FCT_ABORT_DONE)) { 264 /* IOCB ULPCOMMAND is saved after EMLXS_FCT_IOCB_ISSUED */ 265 if (iop->trc[iop->trc[0]-1] == EMLXS_FCT_IOCB_ISSUED) { 266 iop->trc[0]++; 267 } else { 268 iop->trc[0] = 0; 269 } else { 270 iop->trc[0]++; 271 } 272 mutex_exit(&port->iotrace_mtx); 273 274 return; 275 276 } /* emlxs_fct_io_trace() */ 277 #endif /* FCT_IO_TRACE */ 278 279 #ifdef MODSYM_SUPPORT 280 281 extern int 282 emlxs_fct_modopen() 283 { 284 int err; 285 286 mutex_enter(&emlxs_device.lock); 287 288 if (emlxs_modsym.fct_modopen) { 289 mutex_exit(&emlxs_device.lock); 290 return (0); 291 } 292 293 emlxs_modsym.fct_modopen++; 294 295 /* Comstar (fct) */ 296 err = 0; 297 emlxs_modsym.mod_fct = ddi_modopen("drv/fct", KRTLD_MODE_FIRST, &err); 298 if (!emlxs_modsym.mod_fct) { 299 300 cmn_err(CE_WARN, "?%s: ddi_modopen drv/fct failed: err %d", 301 DRIVER_NAME, err); 302 goto failed; 303 } 304 305 /* Comstar (stmf) */ 306 err = 0; 307 emlxs_modsym.mod_stmf = 308 ddi_modopen("drv/stmf", KRTLD_MODE_FIRST, &err); 309 if (!emlxs_modsym.mod_stmf) { 310 311 cmn_err(CE_WARN, "?%s: ddi_modopen drv/stmf failed: err %d", 312 DRIVER_NAME, err); 313 goto failed; 314 } 315 316 err = 0; 317 /* Check if the fct fct_alloc is present */ 318 emlxs_modsym.fct_alloc = (void *(*)())ddi_modsym(emlxs_modsym.mod_fct, 319 "fct_alloc", &err); 320 if ((void *)emlxs_modsym.fct_alloc == NULL) { 321 cmn_err(CE_WARN, 322 "?%s: drv/fct: fct_alloc not present", DRIVER_NAME); 323 goto failed; 324 } 325 326 err = 0; 327 /* Check if the fct fct_free is present */ 328 emlxs_modsym.fct_free = (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 329 "fct_free", &err); 330 if ((void *)emlxs_modsym.fct_free == NULL) { 331 cmn_err(CE_WARN, 332 "?%s: drv/fct: fct_free not present", DRIVER_NAME); 333 goto failed; 334 } 335 336 err = 0; 337 /* Check if the fct fct_scsi_task_alloc is present */ 338 emlxs_modsym.fct_scsi_task_alloc = 339 (void *(*)(void *, uint16_t, uint32_t, uint8_t *, 340 uint16_t, uint16_t))ddi_modsym(emlxs_modsym.mod_fct, 341 "fct_scsi_task_alloc", &err); 342 if ((void *)emlxs_modsym.fct_scsi_task_alloc == NULL) { 343 cmn_err(CE_WARN, 344 "?%s: drv/fct: fct_scsi_task_alloc not present", 345 DRIVER_NAME); 346 goto failed; 347 } 348 349 err = 0; 350 /* Check if the fct fct_register_local_port is present */ 351 emlxs_modsym.fct_register_local_port = 352 (int (*)())ddi_modsym(emlxs_modsym.mod_fct, 353 "fct_register_local_port", &err); 354 if ((void *)emlxs_modsym.fct_register_local_port == NULL) { 355 cmn_err(CE_WARN, 356 "?%s: drv/fct: fct_register_local_port not present", 357 DRIVER_NAME); 358 goto failed; 359 } 360 361 err = 0; 362 /* Check if the fct fct_deregister_local_port is present */ 363 emlxs_modsym.fct_deregister_local_port = 364 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 365 "fct_deregister_local_port", &err); 366 if ((void *)emlxs_modsym.fct_deregister_local_port == NULL) { 367 cmn_err(CE_WARN, 368 "?%s: drv/fct: fct_deregister_local_port not present", 369 DRIVER_NAME); 370 goto failed; 371 } 372 373 err = 0; 374 /* Check if the fct fct_handle_event is present */ 375 emlxs_modsym.fct_handle_event = 376 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_handle_event", 377 &err); 378 if ((void *)emlxs_modsym.fct_handle_event == NULL) { 379 cmn_err(CE_WARN, 380 "?%s: drv/fct: fct_handle_event not present", 381 DRIVER_NAME); 382 goto failed; 383 } 384 385 err = 0; 386 /* Check if the fct fct_post_rcvd_cmd is present */ 387 emlxs_modsym.fct_post_rcvd_cmd = 388 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_post_rcvd_cmd", 389 &err); 390 if ((void *)emlxs_modsym.fct_post_rcvd_cmd == NULL) { 391 cmn_err(CE_WARN, 392 "?%s: drv/fct: fct_post_rcvd_cmd not present", 393 DRIVER_NAME); 394 goto failed; 395 } 396 err = 0; 397 /* Check if the fct fct_alloc is present */ 398 emlxs_modsym.fct_ctl = (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 399 "fct_ctl", &err); 400 if ((void *)emlxs_modsym.fct_ctl == NULL) { 401 cmn_err(CE_WARN, 402 "?%s: drv/fct: fct_ctl not present", DRIVER_NAME); 403 goto failed; 404 } 405 err = 0; 406 /* Check if the fct fct_queue_cmd_for_termination is present */ 407 emlxs_modsym.fct_queue_cmd_for_termination = 408 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 409 "fct_queue_cmd_for_termination", &err); 410 if ((void *)emlxs_modsym.fct_queue_cmd_for_termination == NULL) { 411 cmn_err(CE_WARN, 412 "?%s: drv/fct: fct_queue_cmd_for_termination not present", 413 DRIVER_NAME); 414 goto failed; 415 } 416 err = 0; 417 /* Check if the fct fct_send_response_done is present */ 418 emlxs_modsym.fct_send_response_done = 419 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 420 "fct_send_response_done", &err); 421 if ((void *)emlxs_modsym.fct_send_response_done == NULL) { 422 cmn_err(CE_WARN, 423 "?%s: drv/fct: fct_send_response_done not present", 424 DRIVER_NAME); 425 goto failed; 426 } 427 err = 0; 428 /* Check if the fct fct_send_cmd_done is present */ 429 emlxs_modsym.fct_send_cmd_done = 430 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, "fct_send_cmd_done", 431 &err); 432 if ((void *)emlxs_modsym.fct_send_cmd_done == NULL) { 433 cmn_err(CE_WARN, 434 "?%s: drv/fct: fct_send_cmd_done not present", 435 DRIVER_NAME); 436 goto failed; 437 } 438 err = 0; 439 /* Check if the fct fct_scsi_xfer_data_done is present */ 440 emlxs_modsym.fct_scsi_data_xfer_done = 441 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 442 "fct_scsi_data_xfer_done", &err); 443 if ((void *)emlxs_modsym.fct_scsi_data_xfer_done == NULL) { 444 cmn_err(CE_WARN, 445 "?%s: drv/fct: fct_scsi_data_xfer_done not present", 446 DRIVER_NAME); 447 goto failed; 448 } 449 err = 0; 450 /* Check if the fct fct_port_shutdown is present */ 451 emlxs_modsym.fct_port_shutdown = 452 (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct, 453 "fct_port_shutdown", &err); 454 if ((void *)emlxs_modsym.fct_port_shutdown == NULL) { 455 cmn_err(CE_WARN, 456 "?%s: drv/fct: fct_port_shutdown not present", 457 DRIVER_NAME); 458 goto failed; 459 } 460 461 err = 0; 462 /* Check if the fct fct_port_initialize is present */ 463 emlxs_modsym.fct_port_initialize = 464 (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct, 465 "fct_port_initialize", &err); 466 if ((void *)emlxs_modsym.fct_port_initialize == NULL) { 467 cmn_err(CE_WARN, 468 "?%s: drv/fct: fct_port_initialize not present", 469 DRIVER_NAME); 470 goto failed; 471 } 472 473 err = 0; 474 /* Check if the fct fct_cmd_fca_aborted is present */ 475 emlxs_modsym.fct_cmd_fca_aborted = 476 (void (*)())ddi_modsym(emlxs_modsym.mod_fct, 477 "fct_cmd_fca_aborted", &err); 478 if ((void *)emlxs_modsym.fct_cmd_fca_aborted == NULL) { 479 cmn_err(CE_WARN, 480 "?%s: drv/fct: fct_cmd_fca_aborted not present", 481 DRIVER_NAME); 482 goto failed; 483 } 484 485 err = 0; 486 /* Check if the fct fct_handle_rcvd_flogi is present */ 487 emlxs_modsym.fct_handle_rcvd_flogi = 488 (fct_status_t(*)())ddi_modsym(emlxs_modsym.mod_fct, 489 "fct_handle_rcvd_flogi", &err); 490 if ((void *)emlxs_modsym.fct_handle_rcvd_flogi == NULL) { 491 cmn_err(CE_WARN, 492 "?%s: drv/fct: fct_handle_rcvd_flogi not present", 493 DRIVER_NAME); 494 goto failed; 495 } 496 497 /* Comstar (stmf) */ 498 err = 0; 499 /* Check if the stmf stmf_alloc is present */ 500 emlxs_modsym.stmf_alloc = 501 (void *(*)())ddi_modsym(emlxs_modsym.mod_stmf, "stmf_alloc", 502 &err); 503 if ((void *)emlxs_modsym.stmf_alloc == NULL) { 504 cmn_err(CE_WARN, 505 "?%s: drv/stmf: stmf_alloc not present", DRIVER_NAME); 506 goto failed; 507 } 508 509 err = 0; 510 /* Check if the stmf stmf_free is present */ 511 emlxs_modsym.stmf_free = (void (*)())ddi_modsym(emlxs_modsym.mod_stmf, 512 "stmf_free", &err); 513 if ((void *)emlxs_modsym.stmf_free == NULL) { 514 cmn_err(CE_WARN, 515 "?%s: drv/stmf: stmf_free not present", DRIVER_NAME); 516 goto failed; 517 } 518 519 err = 0; 520 /* Check if the stmf stmf_deregister_port_provider is present */ 521 emlxs_modsym.stmf_deregister_port_provider = 522 (void (*)())ddi_modsym(emlxs_modsym.mod_stmf, 523 "stmf_deregister_port_provider", &err); 524 if ((void *)emlxs_modsym.stmf_deregister_port_provider == NULL) { 525 cmn_err(CE_WARN, 526 "?%s: drv/stmf: stmf_deregister_port_provider not present", 527 DRIVER_NAME); 528 goto failed; 529 } 530 531 err = 0; 532 /* Check if the stmf stmf_register_port_provider is present */ 533 emlxs_modsym.stmf_register_port_provider = 534 (int (*)())ddi_modsym(emlxs_modsym.mod_stmf, 535 "stmf_register_port_provider", &err); 536 if ((void *)emlxs_modsym.stmf_register_port_provider == NULL) { 537 cmn_err(CE_WARN, 538 "?%s: drv/stmf: stmf_register_port_provider not present", 539 DRIVER_NAME); 540 goto failed; 541 } 542 543 mutex_exit(&emlxs_device.lock); 544 return (0); 545 546 failed: 547 548 mutex_exit(&emlxs_device.lock); 549 emlxs_fct_modclose(); 550 return (1); 551 552 } /* emlxs_fct_modopen() */ 553 554 555 extern void 556 emlxs_fct_modclose() 557 { 558 mutex_enter(&emlxs_device.lock); 559 560 if (emlxs_modsym.fct_modopen == 0) { 561 mutex_exit(&emlxs_device.lock); 562 return; 563 } 564 565 emlxs_modsym.fct_modopen--; 566 567 if (emlxs_modsym.fct_modopen) { 568 mutex_exit(&emlxs_device.lock); 569 return; 570 } 571 572 if (emlxs_modsym.mod_fct) { 573 (void) ddi_modclose(emlxs_modsym.mod_fct); 574 emlxs_modsym.mod_fct = 0; 575 } 576 577 if (emlxs_modsym.mod_stmf) { 578 (void) ddi_modclose(emlxs_modsym.mod_stmf); 579 emlxs_modsym.mod_stmf = 0; 580 } 581 582 emlxs_modsym.fct_alloc = NULL; 583 emlxs_modsym.fct_free = NULL; 584 emlxs_modsym.fct_scsi_task_alloc = NULL; 585 emlxs_modsym.fct_register_local_port = NULL; 586 emlxs_modsym.fct_deregister_local_port = NULL; 587 emlxs_modsym.fct_handle_event = NULL; 588 emlxs_modsym.fct_ctl = NULL; 589 emlxs_modsym.fct_queue_cmd_for_termination = NULL; 590 emlxs_modsym.fct_send_response_done = NULL; 591 emlxs_modsym.fct_send_cmd_done = NULL; 592 emlxs_modsym.fct_scsi_data_xfer_done = NULL; 593 emlxs_modsym.fct_port_shutdown = NULL; 594 emlxs_modsym.fct_port_initialize = NULL; 595 emlxs_modsym.fct_cmd_fca_aborted = NULL; 596 emlxs_modsym.fct_handle_rcvd_flogi = NULL; 597 598 emlxs_modsym.stmf_alloc = NULL; 599 emlxs_modsym.stmf_free = NULL; 600 emlxs_modsym.stmf_deregister_port_provider = NULL; 601 emlxs_modsym.stmf_register_port_provider = NULL; 602 603 mutex_exit(&emlxs_device.lock); 604 605 } /* emlxs_fct_modclose() */ 606 607 #endif /* MODSYM_SUPPORT */ 608 609 /* 610 * This routine is called to handle an unsol FLOGI exchange 611 * fx save 612 * 0 1 Process or save port->fx 613 * 0 0 Process or reject port->fx 614 * 1 1 Process port->fx, Process or save fx 615 * 1 0 Process or reject port->fx, Process or reject fx 616 */ 617 static void 618 emlxs_fct_handle_unsol_flogi(emlxs_port_t *port, fct_flogi_xchg_t *fx, 619 uint32_t save) 620 { 621 emlxs_hba_t *hba = HBA; 622 fct_status_t status; 623 IOCBQ iocbq; 624 fct_flogi_xchg_t fxchg; 625 626 begin: 627 mutex_enter(&EMLXS_PORT_LOCK); 628 629 /* Check if there is an old saved FLOGI */ 630 if (port->fx.fx_op) { 631 /* Get it now */ 632 bcopy(&port->fx, &fxchg, sizeof (fct_flogi_xchg_t)); 633 634 if (fx) { 635 /* Save new FLOGI */ 636 bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t)); 637 638 /* Reject old stale FLOGI */ 639 fx = &fxchg; 640 goto reject_it; 641 642 } else { 643 bzero(&port->fx, sizeof (fct_flogi_xchg_t)); 644 fx = &fxchg; 645 } 646 647 } else if (!fx) { 648 /* Nothing to do, just return */ 649 mutex_exit(&EMLXS_PORT_LOCK); 650 return; 651 } 652 653 /* We have a valid FLOGI here */ 654 /* There is no saved FLOGI at this point either */ 655 656 /* Check if COMSTAR is ready to accept it */ 657 if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) { 658 mutex_exit(&EMLXS_PORT_LOCK); 659 660 bzero((uint8_t *)&iocbq, sizeof (IOCBQ)); 661 iocbq.iocb.un.elsreq.remoteID = fx->fx_sid; 662 iocbq.iocb.un.elsreq.myID = fx->fx_did; 663 iocbq.iocb.ULPCONTEXT = (uint16_t)fx->rsvd2; 664 fx->rsvd2 = 0; /* Clear the reserved field now */ 665 666 status = MODSYM(fct_handle_rcvd_flogi) (port->fct_port, fx); 667 668 #ifdef FCT_API_TRACE 669 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 670 "fct_handle_rcvd_flogi %p: status=%x", 671 port->fct_port, status); 672 #endif /* FCT_API_TRACE */ 673 674 if (status == FCT_SUCCESS) { 675 if (fx->fx_op == ELS_OP_ACC) { 676 (void) emlxs_els_reply(port, &iocbq, 677 ELS_CMD_ACC, ELS_CMD_FLOGI, 0, 0); 678 679 } else { /* ELS_OP_LSRJT */ 680 (void) emlxs_els_reply(port, &iocbq, 681 ELS_CMD_LS_RJT, ELS_CMD_FLOGI, 682 fx->fx_rjt_reason, fx->fx_rjt_expl); 683 } 684 } else { 685 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 686 "FLOGI: sid=%x xid=%x. " 687 "fct_handle_rcvd_flogi failed. Rejecting.", 688 fx->fx_sid, iocbq.iocb.ULPCONTEXT); 689 690 (void) emlxs_els_reply(port, &iocbq, 691 ELS_CMD_LS_RJT, ELS_CMD_FLOGI, 692 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 693 } 694 695 return; 696 } 697 698 if (save) { 699 /* Save FLOGI for later */ 700 bcopy(fx, &port->fx, sizeof (fct_flogi_xchg_t)); 701 mutex_exit(&EMLXS_PORT_LOCK); 702 return; 703 } 704 705 reject_it: 706 707 mutex_exit(&EMLXS_PORT_LOCK); 708 709 if (port->fct_flags & FCT_STATE_LINK_UP) { 710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 711 "FLOGI: sid=%x xid=%x. Stale. Rejecting.", 712 fx->fx_sid, fx->rsvd2); 713 714 bzero((uint8_t *)&iocbq, sizeof (IOCBQ)); 715 iocbq.iocb.un.elsreq.remoteID = fx->fx_sid; 716 iocbq.iocb.un.elsreq.myID = fx->fx_did; 717 iocbq.iocb.ULPCONTEXT = fx->rsvd2; 718 719 (void) emlxs_els_reply(port, &iocbq, 720 ELS_CMD_LS_RJT, ELS_CMD_FLOGI, 721 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 722 723 /* If we have an FLOGI saved, try sending it now */ 724 if (port->fx.fx_op) { 725 fx = NULL; 726 goto begin; 727 } 728 729 } else { 730 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 731 "FLOGI: sid=%x xid=%x. Link down. " 732 "Dropping.", 733 fx->fx_sid, fx->rsvd2); 734 } 735 736 return; 737 738 } /* emlxs_fct_handle_unsol_flogi() */ 739 740 741 /* ARGSUSED */ 742 static void 743 emlxs_fct_unsol_flush_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 744 { 745 emlxs_port_t *port = (emlxs_port_t *)arg1; 746 747 emlxs_fct_unsol_flush(port); 748 return; 749 750 } /* emlxs_fct_unsol_flush_thread() */ 751 752 753 /* This is called at port online and offline */ 754 static void 755 emlxs_fct_unsol_flush(emlxs_port_t *port) 756 { 757 emlxs_hba_t *hba = HBA; 758 emlxs_buf_t *cmd_sbp; 759 emlxs_buf_t *next; 760 fct_cmd_t *fct_cmd; 761 fct_status_t rval; 762 uint32_t cmd_code; 763 764 if (!port->fct_port) { 765 return; 766 } 767 768 /* First handle any pending FLOGI */ 769 emlxs_fct_handle_unsol_flogi(port, NULL, 0); 770 771 if ((port->fct_flags & FCT_STATE_LINK_UP_ACKED) && 772 !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) { 773 return; 774 } 775 776 /* Wait queue */ 777 mutex_enter(&EMLXS_PORT_LOCK); 778 cmd_sbp = port->fct_wait_head; 779 port->fct_wait_head = NULL; 780 port->fct_wait_tail = NULL; 781 mutex_exit(&EMLXS_PORT_LOCK); 782 783 /* 784 * Next process any outstanding ELS commands. It doesn't 785 * matter if the Link is up or not, always post them to FCT. 786 */ 787 while (cmd_sbp) { 788 next = cmd_sbp->next; 789 fct_cmd = cmd_sbp->fct_cmd; 790 791 cmd_code = (fct_cmd->cmd_oxid << ELS_CMD_SHIFT); 792 793 /* Reacquire ownership of the fct_cmd */ 794 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 795 if (rval) { 796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 797 "fct_unsol_flush: %s: sid=%x xid=%x " 798 "Unable to reacquire fct_cmd.", 799 emlxs_elscmd_xlate(cmd_code), 800 fct_cmd->cmd_rxid, fct_cmd->cmd_rportid); 801 802 cmd_sbp = next; 803 continue; 804 } 805 /* mutex_enter(&cmd_sbp->fct_mtx); */ 806 807 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 808 "Posting %s: sid=%x xid=%x %p", 809 emlxs_elscmd_xlate(cmd_code), 810 fct_cmd->cmd_rportid, fct_cmd->cmd_rxid, 811 fct_cmd); 812 813 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 814 /* mutex_exit(&cmd_sbp->fct_mtx); */ 815 816 #ifdef FCT_API_TRACE 817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 818 "fct_post_rcvd_cmd:2 %p:%p portid x%x", fct_cmd, cmd_sbp, 819 fct_cmd->cmd_lportid); 820 #endif /* FCT_API_TRACE */ 821 822 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 823 824 cmd_sbp = next; 825 826 } /* while () */ 827 828 return; 829 830 } /* emlxs_fct_unsol_flush() */ 831 832 833 int 834 emlxs_is_digit(uint8_t chr) 835 { 836 if ((chr >= '0') && (chr <= '9')) { 837 return (1); 838 } 839 840 return (0); 841 842 } /* emlxs_is_digit */ 843 844 845 /* 846 * Convert an ASCII decimal numeric string to integer. 847 * Negation character '-' is not handled. 848 */ 849 static uint32_t 850 emlxs_str_atoi(uint8_t *string) 851 { 852 uint32_t num = 0; 853 int i = 0; 854 855 while (string[i]) { 856 if (!emlxs_is_digit(string[i])) { 857 return (num); 858 } 859 860 num = num * 10 + (string[i++] - '0'); 861 } 862 863 return (num); 864 865 } /* emlxs_str_atoi() */ 866 867 868 extern uint32_t 869 emlxs_fct_init(emlxs_hba_t *hba) 870 { 871 emlxs_port_t *port = &PPORT; 872 873 /* Check if COMSTAR is present */ 874 if (((void *)MODSYM(stmf_alloc) == NULL) || 875 ((void *)MODSYM(fct_alloc) == NULL)) { 876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 877 "Comstar not present."); 878 return (1); 879 } 880 881 return (0); 882 883 } /* emlxs_fct_init() */ 884 885 886 extern void 887 emlxs_fct_attach(emlxs_hba_t *hba) 888 { 889 emlxs_port_t *port = &PPORT; 890 uint32_t vpi; 891 892 if (!(port->flag & EMLXS_TGT_ENABLED)) { 893 return; 894 } 895 896 /* Bind the physical port */ 897 emlxs_fct_bind_port(port); 898 899 /* Bind virtual ports */ 900 if (hba->flag & FC_NPIV_ENABLED) { 901 for (vpi = 1; vpi <= hba->vpi_high; vpi++) { 902 port = &VPORT(vpi); 903 904 if (!(port->flag & EMLXS_PORT_ENABLED)) { 905 continue; 906 } 907 908 emlxs_fct_bind_port(port); 909 } 910 } 911 912 return; 913 914 } /* emlxs_fct_attach() */ 915 916 917 extern void 918 emlxs_fct_detach(emlxs_hba_t *hba) 919 { 920 uint32_t i; 921 emlxs_port_t *vport; 922 923 for (i = 0; i < MAX_VPORTS; i++) { 924 vport = &VPORT(i); 925 926 if (!(vport->flag & EMLXS_PORT_ENABLED)) { 927 continue; 928 } 929 930 emlxs_fct_unbind_port(vport); 931 } 932 933 #ifdef FCT_IO_TRACE 934 { 935 emlxs_port_t *port = &PPORT; 936 937 mutex_destroy(&port->iotrace_mtx); 938 if (port->iotrace) { 939 kmem_free(port->iotrace, 940 (port->iotrace_cnt * sizeof (emlxs_iotrace_t))); 941 } 942 port->iotrace = NULL; 943 } 944 #endif /* FCT_IO_TRACE */ 945 946 return; 947 948 } /* emlxs_fct_detach() */ 949 950 951 extern void 952 emlxs_fct_unbind_port(emlxs_port_t *port) 953 { 954 emlxs_hba_t *hba = HBA; 955 char node_name[32]; 956 957 mutex_enter(&EMLXS_PORT_LOCK); 958 959 if (!(port->flag & EMLXS_TGT_BOUND)) { 960 mutex_exit(&EMLXS_PORT_LOCK); 961 return; 962 } 963 964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 965 "fct_unbind_port: port=%d", port->vpi); 966 967 /* Destroy & flush all port nodes, if they exist */ 968 if (port->node_count) { 969 (void) EMLXS_SLI_UNREG_NODE(port, NULL, NULL, NULL, NULL); 970 } 971 972 port->flag &= ~EMLXS_TGT_BOUND; 973 port->flag &= ~EMLXS_TGT_ENABLED; 974 hba->num_of_ports--; 975 mutex_exit(&EMLXS_PORT_LOCK); 976 977 if (port->fct_port) { 978 emlxs_fct_link_down(port); 979 emlxs_fct_unsol_flush(port); 980 981 #ifdef FCT_API_TRACE 982 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 983 "fct_deregister_local_port %p", port->fct_port); 984 #endif /* FCT_API_TRACE */ 985 MODSYM(fct_deregister_local_port) (port->fct_port); 986 987 if (port->fct_port->port_fds) { 988 #ifdef FCT_API_TRACE 989 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 990 "fct_free:3 %p", port->fct_port->port_fds); 991 #endif /* FCT_API_TRACE */ 992 MODSYM(fct_free) (port->fct_port->port_fds); 993 port->fct_port->port_fds = NULL; 994 } 995 #ifdef FCT_API_TRACE 996 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 997 "fct_free:4 %p", port->fct_port); 998 #endif /* FCT_API_TRACE */ 999 MODSYM(fct_free) (port->fct_port); 1000 port->fct_port = NULL; 1001 port->fct_flags = 0; 1002 } 1003 1004 if (port->port_provider) { 1005 #ifdef FCT_API_TRACE 1006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1007 "stmf_deregister_port_provider:1 %p", 1008 port->port_provider); 1009 #endif /* FCT_API_TRACE */ 1010 MODSYM(stmf_deregister_port_provider) (port->port_provider); 1011 1012 #ifdef FCT_API_TRACE 1013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1014 "stmf_free:1 %p", port->port_provider); 1015 #endif /* FCT_API_TRACE */ 1016 MODSYM(stmf_free) (port->port_provider); 1017 port->port_provider = NULL; 1018 } 1019 1020 if (port->fct_memseg) { 1021 emlxs_fct_dmem_fini(port); 1022 } 1023 1024 (void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT", 1025 hba->ddiinst, port->vpi); 1026 (void) ddi_remove_minor_node(hba->dip, node_name); 1027 1028 return; 1029 1030 } /* emlxs_fct_unbind_port() */ 1031 1032 1033 extern void 1034 emlxs_fct_bind_port(emlxs_port_t *port) 1035 { 1036 emlxs_hba_t *hba = HBA; 1037 fct_local_port_t *fct_port; 1038 uint32_t flag = 0; 1039 emlxs_config_t *cfg = &CFG; 1040 fct_dbuf_store_t *fds; 1041 char node_name[32]; 1042 uint8_t *bptr; 1043 1044 if (!(port->flag & EMLXS_TGT_ENABLED)) { 1045 return; 1046 } 1047 1048 mutex_enter(&EMLXS_PORT_LOCK); 1049 1050 if (port->flag & EMLXS_TGT_BOUND) { 1051 mutex_exit(&EMLXS_PORT_LOCK); 1052 return; 1053 } 1054 1055 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1056 "fct_bind_port: port=%d", port->vpi); 1057 1058 /* Perform generic port initialization */ 1059 emlxs_port_init(port); 1060 1061 if (port->vpi == 0) { 1062 (void) snprintf(port->cfd_name, sizeof (port->cfd_name), 1063 "%s%d", DRIVER_NAME, hba->ddiinst); 1064 } else { 1065 (void) snprintf(port->cfd_name, sizeof (port->cfd_name), 1066 "%s%d.%d", DRIVER_NAME, hba->ddiinst, port->vpi); 1067 } 1068 1069 if (emlxs_fct_dmem_init(port) != FCT_SUCCESS) { 1070 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1071 "fct_bind_port: Unable to allocate fct memory."); 1072 goto failed; 1073 } 1074 flag |= 0x00000001; 1075 1076 port->port_provider = 1077 (stmf_port_provider_t *) 1078 MODSYM(stmf_alloc) (STMF_STRUCT_PORT_PROVIDER, 0, 0); 1079 #ifdef FCT_API_TRACE 1080 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1081 "stmf_alloc port_provider %p", port->port_provider); 1082 #endif /* FCT_API_TRACE */ 1083 1084 if (port->port_provider == NULL) { 1085 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1086 "fct_bind_port: Unable to allocate port provider."); 1087 goto failed; 1088 } 1089 flag |= 0x00000002; 1090 1091 port->port_provider->pp_portif_rev = PORTIF_REV_1; 1092 port->port_provider->pp_name = port->cfd_name; 1093 port->port_provider->pp_provider_private = port; 1094 1095 #ifdef FCT_API_TRACE 1096 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1097 "stmf_register_port_provider %p", port->port_provider); 1098 #endif /* FCT_API_TRACE */ 1099 /* register port provider with framework */ 1100 if (MODSYM(stmf_register_port_provider) (port->port_provider) != 1101 STMF_SUCCESS) { 1102 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1103 "fct_bind_port: Unable to register port provider."); 1104 goto failed; 1105 } 1106 flag |= 0x00000004; 1107 1108 port->fct_port = 1109 (fct_local_port_t *)MODSYM(fct_alloc) (FCT_STRUCT_LOCAL_PORT, 0, 1110 0); 1111 #ifdef FCT_API_TRACE 1112 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1113 "fct_alloc fct_port %p", port->fct_port); 1114 #endif /* FCT_API_TRACE */ 1115 1116 if (port->fct_port == NULL) { 1117 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1118 "fct_bind_port: Unable to allocate fct port."); 1119 goto failed; 1120 } 1121 flag |= 0x00000008; 1122 1123 port->fct_port->port_fds = 1124 (fct_dbuf_store_t *)MODSYM(fct_alloc) (FCT_STRUCT_DBUF_STORE, 0, 1125 0); 1126 #ifdef FCT_API_TRACE 1127 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1128 "fct_alloc port_fds %p", port->fct_port->port_fds); 1129 #endif /* FCT_API_TRACE */ 1130 1131 if (port->fct_port->port_fds == NULL) { 1132 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1133 "fct_bind_port: Unable to allocate dbuf store."); 1134 goto failed; 1135 } 1136 flag |= 0x00000010; 1137 1138 (void) snprintf(node_name, sizeof (node_name), "%d,%d:SFCT", 1139 hba->ddiinst, port->vpi); 1140 if (ddi_create_minor_node(hba->dip, node_name, S_IFCHR, hba->ddiinst, 1141 NULL, 0) == DDI_FAILURE) { 1142 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1143 "Unable to create SFCT device node."); 1144 goto failed; 1145 } 1146 flag |= 0x00000020; 1147 1148 /* Intialize */ 1149 fct_port = port->fct_port; 1150 fct_port->port_fca_version = FCT_FCA_MODREV_1; 1151 fct_port->port_fca_private = port; 1152 fct_port->port_fca_abort_timeout = 30 * 1000; /* 30 seconds */ 1153 1154 bcopy((uint8_t *)&port->wwpn, (uint8_t *)fct_port->port_pwwn, 8); 1155 bcopy((uint8_t *)&port->wwnn, (uint8_t *)fct_port->port_nwwn, 8); 1156 1157 bptr = (uint8_t *)&port->wwnn; 1158 (void) snprintf(fct_port->port_nwwn_str, FC_WWN_BUFLEN, 1159 "%02x%02x%02x%02x%02x%02x%02x%02x", 1160 bptr[0], bptr[1], bptr[2], bptr[3], 1161 bptr[4], bptr[5], bptr[6], bptr[7]); 1162 1163 bptr = (uint8_t *)&port->wwpn; 1164 (void) snprintf(fct_port->port_pwwn_str, FC_WWN_BUFLEN, 1165 "%02x%02x%02x%02x%02x%02x%02x%02x", 1166 bptr[0], bptr[1], bptr[2], bptr[3], 1167 bptr[4], bptr[5], bptr[6], bptr[7]); 1168 1169 fct_port->port_sym_node_name = port->snn; 1170 fct_port->port_sym_port_name = port->spn; 1171 fct_port->port_hard_address = cfg[CFG_ASSIGN_ALPA].current; 1172 fct_port->port_default_alias = port->cfd_name; 1173 fct_port->port_pp = port->port_provider; 1174 fct_port->port_max_logins = hba->max_nodes + EMLXS_FCT_NUM_ELS_ONLY; 1175 1176 if (cfg[CFG_FCT_QDEPTH].current && 1177 (cfg[CFG_FCT_QDEPTH].current < hba->io_throttle)) { 1178 fct_port->port_max_xchges = cfg[CFG_FCT_QDEPTH].current; 1179 } else { 1180 fct_port->port_max_xchges = hba->io_throttle; 1181 } 1182 1183 fct_port->port_fca_fcp_cmd_size = sizeof (emlxs_buf_t); 1184 fct_port->port_fca_rp_private_size = sizeof (uintptr_t); 1185 fct_port->port_fca_sol_els_private_size = sizeof (emlxs_buf_t); 1186 fct_port->port_fca_sol_ct_private_size = sizeof (emlxs_buf_t); 1187 fct_port->port_get_link_info = emlxs_fct_get_link_info; 1188 fct_port->port_register_remote_port = emlxs_fct_register_remote_port; 1189 fct_port->port_deregister_remote_port = 1190 emlxs_fct_deregister_remote_port; 1191 fct_port->port_send_cmd = emlxs_fct_send_cmd; 1192 fct_port->port_xfer_scsi_data = emlxs_fct_send_fcp_data; 1193 fct_port->port_send_cmd_response = emlxs_fct_send_cmd_rsp; 1194 fct_port->port_abort_cmd = emlxs_fct_abort; 1195 fct_port->port_ctl = emlxs_fct_ctl; 1196 fct_port->port_flogi_xchg = emlxs_fct_flogi_xchg; 1197 fct_port->port_populate_hba_details = emlxs_fct_populate_hba_details; 1198 fct_port->port_info = emlxs_fct_port_info; 1199 1200 fds = port->fct_port->port_fds; 1201 fds->fds_fca_private = port; 1202 fds->fds_alloc_data_buf = emlxs_fct_dbuf_alloc; 1203 fds->fds_free_data_buf = emlxs_fct_dbuf_free; 1204 1205 /* Scatter gather list support */ 1206 /* fds->fds_setup_dbuf = ; */ 1207 /* fds->fds_teardown_dbuf = ; */ 1208 /* fds->fds_max_sgl_xfer_len = ; */ 1209 /* fds->fds_copy_threshold = ; */ 1210 1211 #ifdef FCT_API_TRACE 1212 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1213 "fct_register_local_port %p", fct_port); 1214 #endif /* FCT_API_TRACE */ 1215 /* register this local port with the fct module */ 1216 if (MODSYM(fct_register_local_port) (fct_port) != FCT_SUCCESS) { 1217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1218 "fct_bind_port: Unable to register fct port."); 1219 goto failed; 1220 } 1221 1222 /* Set the bound flag */ 1223 port->flag |= EMLXS_TGT_BOUND; 1224 hba->num_of_ports++; 1225 1226 mutex_exit(&EMLXS_PORT_LOCK); 1227 1228 return; 1229 1230 failed: 1231 1232 if (flag & 0x20) { 1233 (void) ddi_remove_minor_node(hba->dip, node_name); 1234 } 1235 1236 if (flag & 0x10) { 1237 #ifdef FCT_API_TRACE 1238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1239 "fct_free:5 %p", port->fct_port->port_fds); 1240 #endif /* FCT_API_TRACE */ 1241 MODSYM(fct_free) (port->fct_port->port_fds); 1242 port->fct_port->port_fds = NULL; 1243 } 1244 1245 if (flag & 0x8) { 1246 #ifdef FCT_API_TRACE 1247 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1248 "fct_free:6 %p", port->fct_port); 1249 #endif /* FCT_API_TRACE */ 1250 MODSYM(fct_free) (port->fct_port); 1251 port->fct_port = NULL; 1252 port->fct_flags = 0; 1253 } 1254 1255 if (flag & 0x4) { 1256 #ifdef FCT_API_TRACE 1257 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1258 "stmf_deregister_port_provider:2 %p", 1259 port->port_provider); 1260 #endif /* FCT_API_TRACE */ 1261 MODSYM(stmf_deregister_port_provider) (port->port_provider); 1262 } 1263 1264 if (flag & 0x2) { 1265 #ifdef FCT_API_TRACE 1266 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1267 "stmf_free:2 %p", port->port_provider); 1268 #endif /* FCT_API_TRACE */ 1269 MODSYM(stmf_free) (port->port_provider); 1270 port->port_provider = NULL; 1271 } 1272 1273 if (flag & 0x1) { 1274 emlxs_fct_dmem_fini(port); 1275 } 1276 1277 port->flag &= ~EMLXS_TGT_ENABLED; 1278 1279 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1280 "Target mode disabled."); 1281 1282 mutex_exit(&EMLXS_PORT_LOCK); 1283 1284 return; 1285 1286 } /* emlxs_fct_bind_port() */ 1287 1288 1289 /* COMSTAR ENTER POINT */ 1290 /*ARGSUSED*/ 1291 static fct_status_t 1292 emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg, 1293 uint8_t *buffer, uint32_t *size) 1294 { 1295 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 1296 emlxs_hba_t *hba = HBA; 1297 fct_status_t rval = FCT_SUCCESS; 1298 fct_port_link_status_t *link_status; 1299 MAILBOX *mb; 1300 MAILBOXQ *mbq; 1301 1302 switch (cmd) { 1303 case FC_TGT_PORT_RLS: 1304 bzero(buffer, *size); 1305 1306 if ((*size) < sizeof (fct_port_link_status_t)) { 1307 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1308 "FC_TGT_PORT_RLS: Buffer too small. %d < %d", 1309 *size, sizeof (fct_port_link_status_t)); 1310 1311 rval = FCT_FAILURE; 1312 break; 1313 } 1314 1315 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) { 1316 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1317 "FC_TGT_PORT_RLS: Unable to allocate mailbox."); 1318 1319 rval = FCT_ALLOC_FAILURE; 1320 break; 1321 } 1322 mb = (MAILBOX *)mbq; 1323 1324 emlxs_mb_read_lnk_stat(hba, mbq); 1325 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) 1326 != MBX_SUCCESS) { 1327 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1328 "FC_TGT_PORT_RLS: Unable to send request."); 1329 1330 rval = FCT_BUSY; 1331 } else { 1332 link_status = (fct_port_link_status_t *)buffer; 1333 link_status->LinkFailureCount = 1334 mb->un.varRdLnk.linkFailureCnt; 1335 link_status->LossOfSyncCount = 1336 mb->un.varRdLnk.lossSyncCnt; 1337 link_status->LossOfSignalsCount = 1338 mb->un.varRdLnk.lossSignalCnt; 1339 link_status->PrimitiveSeqProtocolErrorCount = 1340 mb->un.varRdLnk.primSeqErrCnt; 1341 link_status->InvalidTransmissionWordCount = 1342 mb->un.varRdLnk.invalidXmitWord; 1343 link_status->InvalidCRCCount = 1344 mb->un.varRdLnk.crcCnt; 1345 } 1346 1347 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1348 break; 1349 1350 default: 1351 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 1352 "fct_port_info: Invalid request. cmd=%x", 1353 cmd); 1354 1355 rval = FCT_FAILURE; 1356 break; 1357 1358 } 1359 1360 return (rval); 1361 1362 } /* emlxs_fct_port_info() */ 1363 1364 1365 /* COMSTAR ENTER POINT */ 1366 static void 1367 emlxs_fct_populate_hba_details(fct_local_port_t *fct_port, 1368 fct_port_attrs_t *port_attrs) 1369 { 1370 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 1371 emlxs_hba_t *hba = HBA; 1372 emlxs_vpd_t *vpd = &VPD; 1373 1374 (void) strncpy(port_attrs->manufacturer, "Emulex", 1375 (sizeof (port_attrs->manufacturer)-1)); 1376 (void) strncpy(port_attrs->serial_number, vpd->serial_num, 1377 (sizeof (port_attrs->serial_number)-1)); 1378 (void) strncpy(port_attrs->model, hba->model_info.model, 1379 (sizeof (port_attrs->model)-1)); 1380 (void) strncpy(port_attrs->model_description, 1381 hba->model_info.model_desc, 1382 (sizeof (port_attrs->model_description)-1)); 1383 (void) snprintf(port_attrs->hardware_version, 1384 (sizeof (port_attrs->hardware_version)-1), 1385 "%x", vpd->biuRev); 1386 (void) snprintf(port_attrs->driver_version, 1387 (sizeof (port_attrs->driver_version)-1), 1388 "%s (%s)", emlxs_version, 1389 emlxs_revision); 1390 (void) strncpy(port_attrs->option_rom_version, vpd->fcode_version, 1391 (sizeof (port_attrs->option_rom_version)-1)); 1392 (void) snprintf(port_attrs->firmware_version, 1393 (sizeof (port_attrs->firmware_version)-1), 1394 "%s (%s)", vpd->fw_version, 1395 vpd->fw_label); 1396 (void) strncpy(port_attrs->driver_name, DRIVER_NAME, 1397 (sizeof (port_attrs->driver_name)-1)); 1398 port_attrs->vendor_specific_id = 1399 ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX); 1400 port_attrs->supported_cos = LE_SWAP32(FC_NS_CLASS3); 1401 1402 port_attrs->max_frame_size = FF_FRAME_SIZE; 1403 1404 if (vpd->link_speed & LMT_16GB_CAPABLE) { 1405 port_attrs->supported_speed |= PORT_SPEED_16G; 1406 } 1407 if (vpd->link_speed & LMT_10GB_CAPABLE) { 1408 port_attrs->supported_speed |= PORT_SPEED_10G; 1409 } 1410 if (vpd->link_speed & LMT_8GB_CAPABLE) { 1411 port_attrs->supported_speed |= PORT_SPEED_8G; 1412 } 1413 if (vpd->link_speed & LMT_4GB_CAPABLE) { 1414 port_attrs->supported_speed |= PORT_SPEED_4G; 1415 } 1416 if (vpd->link_speed & LMT_2GB_CAPABLE) { 1417 port_attrs->supported_speed |= PORT_SPEED_2G; 1418 } 1419 if (vpd->link_speed & LMT_1GB_CAPABLE) { 1420 port_attrs->supported_speed |= PORT_SPEED_1G; 1421 } 1422 1423 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1424 "Port attr: manufacturer = %s", port_attrs->manufacturer); 1425 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1426 "Port attr: serial_num = %s", port_attrs->serial_number); 1427 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1428 "Port attr: model = %s", port_attrs->model); 1429 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1430 "Port attr: model_description = %s", 1431 port_attrs->model_description); 1432 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1433 "Port attr: hardware_version = %s", 1434 port_attrs->hardware_version); 1435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1436 "Port attr: driver_version = %s", port_attrs->driver_version); 1437 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1438 "Port attr: option_rom_version = %s", 1439 port_attrs->option_rom_version); 1440 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1441 "Port attr: firmware_version = %s", 1442 port_attrs->firmware_version); 1443 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1444 "Port attr: driver_name = %s", port_attrs->driver_name); 1445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1446 "Port attr: vendor_specific_id = 0x%x", 1447 port_attrs->vendor_specific_id); 1448 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1449 "Port attr: supported_cos = 0x%x", 1450 port_attrs->supported_cos); 1451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1452 "Port attr: supported_speed = 0x%x", 1453 port_attrs->supported_speed); 1454 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1455 "Port attr: max_frame_size = 0x%x", 1456 port_attrs->max_frame_size); 1457 1458 return; 1459 1460 } /* emlxs_fct_populate_hba_details() */ 1461 1462 1463 /* COMSTAR ENTER POINT */ 1464 /* ARGSUSED */ 1465 static void 1466 emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg) 1467 { 1468 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 1469 emlxs_hba_t *hba = HBA; 1470 stmf_change_status_t st; 1471 1472 st.st_completion_status = FCT_SUCCESS; 1473 st.st_additional_info = NULL; 1474 1475 switch (cmd) { 1476 case FCT_CMD_PORT_ONLINE: 1477 /* If the HBA is offline, we cannot bring the tgtport online */ 1478 if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) { 1479 st.st_completion_status = FCT_FAILURE; 1480 MODSYM(fct_ctl) (fct_port->port_lport, 1481 FCT_CMD_PORT_ONLINE_COMPLETE, &st); 1482 break; 1483 } 1484 1485 if (port->fct_flags & FCT_STATE_PORT_ONLINE) { 1486 st.st_completion_status = STMF_ALREADY; 1487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1488 "STATE: ONLINE chk"); 1489 } else { 1490 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1491 "STATE: OFFLINE --> ONLINE"); 1492 1493 port->fct_flags |= FCT_STATE_NOT_ACKED; 1494 port->fct_flags |= FCT_STATE_PORT_ONLINE; 1495 1496 if ((port->vpi == 0) && 1497 (port->mode == MODE_TARGET) && 1498 (hba->state <= FC_LINK_DOWN)) { 1499 /* Try to bring the link up */ 1500 (void) emlxs_reset_link(hba, 1, 1); 1501 } 1502 1503 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1504 "STATE: ONLINE"); 1505 } 1506 1507 MODSYM(fct_ctl) (fct_port->port_lport, 1508 FCT_CMD_PORT_ONLINE_COMPLETE, &st); 1509 break; 1510 1511 case FCT_CMD_PORT_OFFLINE: 1512 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 1513 st.st_completion_status = STMF_ALREADY; 1514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1515 "STATE: OFFLINE chk"); 1516 1517 } else { 1518 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1519 "STATE: ONLINE --> OFFLINE"); 1520 1521 /* Take link down and flush */ 1522 emlxs_fct_link_down(port); 1523 emlxs_fct_unsol_flush(port); 1524 1525 /* Declare this port offline now */ 1526 port->fct_flags |= FCT_STATE_NOT_ACKED; 1527 port->fct_flags &= ~FCT_STATE_PORT_ONLINE; 1528 1529 if ((port->vpi == 0) && 1530 (port->mode == MODE_TARGET) && 1531 !(port->flag & EMLXS_INI_ENABLED)) { 1532 /* Take link down and hold it down */ 1533 (void) emlxs_reset_link(hba, 0, 1); 1534 } 1535 1536 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1537 "STATE: OFFLINE"); 1538 } 1539 1540 MODSYM(fct_ctl) (fct_port->port_lport, 1541 FCT_CMD_PORT_OFFLINE_COMPLETE, &st); 1542 1543 break; 1544 1545 case FCT_ACK_PORT_OFFLINE_COMPLETE: 1546 port->fct_flags &= ~FCT_STATE_NOT_ACKED; 1547 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1548 "STATE: OFFLINE ack"); 1549 break; 1550 1551 case FCT_ACK_PORT_ONLINE_COMPLETE: 1552 port->fct_flags &= ~FCT_STATE_NOT_ACKED; 1553 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1554 "STATE: ONLINE ack"); 1555 break; 1556 1557 case FCT_CMD_FORCE_LIP: 1558 if (port->mode == MODE_INITIATOR) { 1559 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1560 "fct_ctl: FCT_CMD_FORCE_LIP."); 1561 break; 1562 } 1563 1564 if (hba->fw_flag & FW_UPDATE_NEEDED) { 1565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1566 "fct_ctl: FCT_CMD_FORCE_LIP -> " 1567 "FCT_CMD_RESET"); 1568 1569 hba->fw_flag |= FW_UPDATE_KERNEL; 1570 1571 /* Reset the adapter */ 1572 (void) emlxs_reset(port, FC_FCA_RESET); 1573 } else { 1574 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1575 "fct_ctl: FCT_CMD_FORCE_LIP"); 1576 1577 /* Reset the link */ 1578 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 1579 } 1580 break; 1581 } 1582 1583 return; 1584 1585 } /* emlxs_fct_ctl() */ 1586 1587 1588 extern int 1589 emlxs_fct_port_shutdown(emlxs_port_t *port) 1590 { 1591 fct_local_port_t *fct_port; 1592 int i; 1593 1594 fct_port = port->fct_port; 1595 if (!fct_port) { 1596 return (0); 1597 } 1598 1599 port->fct_flags |= FCT_STATE_NOT_ACKED; 1600 1601 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "fct_port_shutdown"); 1602 MODSYM(fct_port_shutdown) (fct_port, STMF_RFLAG_STAY_OFFLINED, 1603 DRIVER_NAME" shutdown"); 1604 1605 i = 0; 1606 while (port->fct_flags & FCT_STATE_NOT_ACKED) { 1607 i++; 1608 if (i > 300) { /* 30 seconds */ 1609 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1610 "fct_port_shutdown failed to ACK"); 1611 break; 1612 } 1613 delay(drv_usectohz(100000)); /* 100 msec */ 1614 } 1615 return (1); 1616 } 1617 1618 1619 extern int 1620 emlxs_fct_port_initialize(emlxs_port_t *port) 1621 { 1622 fct_local_port_t *fct_port; 1623 int i; 1624 1625 fct_port = port->fct_port; 1626 if (!fct_port) { 1627 return (0); 1628 } 1629 1630 port->fct_flags |= FCT_STATE_NOT_ACKED; 1631 1632 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1633 "fct_port_initialize"); 1634 MODSYM(fct_port_initialize) (fct_port, STMF_RFLAG_STAY_OFFLINED, 1635 DRIVER_NAME" initialize"); 1636 1637 i = 0; 1638 while (port->fct_flags & FCT_STATE_NOT_ACKED) { 1639 i++; 1640 if (i > 300) { /* 30 seconds */ 1641 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1642 "fct_port_initialize failed to ACK"); 1643 break; 1644 } 1645 delay(drv_usectohz(100000)); /* 100 msec */ 1646 } 1647 return (1); 1648 } 1649 1650 1651 /* COMSTAR ENTER POINT */ 1652 static fct_status_t 1653 emlxs_fct_send_cmd(fct_cmd_t *fct_cmd) 1654 { 1655 emlxs_port_t *port; 1656 1657 port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 1658 1659 #ifdef FCT_API_TRACE 1660 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1661 "fct_send_cmd %p:%p x%x", fct_cmd, 1662 fct_cmd->cmd_fca_private, fct_cmd->cmd_type); 1663 #endif /* FCT_API_TRACE */ 1664 1665 switch (fct_cmd->cmd_type) { 1666 case FCT_CMD_SOL_ELS: 1667 1668 return (emlxs_fct_send_els_cmd(fct_cmd)); 1669 1670 case FCT_CMD_SOL_CT: 1671 1672 return (emlxs_fct_send_ct_cmd(fct_cmd)); 1673 1674 default: 1675 1676 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1677 "fct_send_cmd: Invalid cmd type found. type=%x", 1678 fct_cmd->cmd_type); 1679 1680 return (FCT_FAILURE); 1681 } 1682 1683 } /* emlxs_fct_send_cmd() */ 1684 1685 1686 /* COMSTAR ENTER POINT */ 1687 static fct_status_t 1688 emlxs_fct_send_cmd_rsp(fct_cmd_t *fct_cmd, uint32_t ioflags) 1689 { 1690 emlxs_port_t *port; 1691 emlxs_buf_t *cmd_sbp; 1692 fct_status_t rval; 1693 IOCBQ *iocbq; 1694 IOCB *iocb; 1695 uint32_t status; 1696 1697 port = (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 1698 1699 rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_CMD_RSP); 1700 if (rval) { 1701 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1702 "fct_send_cmd_rsp: " 1703 "Unable to accept fct_cmd. type=%x", 1704 fct_cmd->cmd_type); 1705 1706 return (rval); 1707 } 1708 /* mutex_enter(&cmd_sbp->fct_mtx); */ 1709 1710 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 1711 iocbq = &cmd_sbp->iocbq; 1712 iocbq->sbp = cmd_sbp; 1713 iocb = &iocbq->iocb; 1714 status = iocb->ULPSTATUS; 1715 1716 #ifdef FCT_API_TRACE 1717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1718 "fct_send_cmd_rsp %p:%p x%x, %x, %x", 1719 fct_cmd, cmd_sbp, fct_cmd->cmd_type, iocb->ULPCT, status); 1720 #endif /* FCT_API_TRACE */ 1721 1722 switch (fct_cmd->cmd_type) { 1723 case FCT_CMD_FCP_XCHG: 1724 1725 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 1726 goto failure; 1727 } 1728 1729 if ((iocb->ULPCT == 0x1) && (status == 0)) { 1730 1731 /* Firmware already sent out resp */ 1732 cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS; 1733 1734 TGTPORTSTAT.FctOutstandingIO--; 1735 1736 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 1737 /* mutex_exit(&cmd_sbp->fct_mtx); */ 1738 1739 #ifdef FCT_API_TRACE 1740 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1741 "fct_send_response_done:4 %p: x%x", 1742 fct_cmd, fct_cmd->cmd_comp_status); 1743 1744 #endif /* FCT_API_TRACE */ 1745 1746 MODSYM(fct_send_response_done) (fct_cmd, 1747 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 1748 1749 return (FCT_SUCCESS); 1750 } 1751 1752 rval = emlxs_fct_send_fcp_status(fct_cmd); 1753 if (rval == FCT_NOT_FOUND) { 1754 goto failure; 1755 } 1756 /* mutex_exit(&cmd_sbp->fct_mtx); */ 1757 1758 return (rval); 1759 1760 case FCT_CMD_RCVD_ELS: 1761 1762 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 1763 goto failure; 1764 } 1765 1766 rval = emlxs_fct_send_els_rsp(fct_cmd); 1767 /* mutex_exit(&cmd_sbp->fct_mtx); */ 1768 1769 return (rval); 1770 1771 default: 1772 1773 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 1774 fct_cmd->cmd_handle = 0; 1775 } 1776 1777 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1778 "fct_send_cmd_rsp: Invalid cmd type found. type=%x", 1779 fct_cmd->cmd_type); 1780 1781 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 1782 /* mutex_exit(&cmd_sbp->fct_mtx); */ 1783 1784 return (FCT_FAILURE); 1785 } 1786 1787 failure: 1788 1789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1790 "fct_send_cmd_rsp: " 1791 "Unable to handle FCT_IOF_FORCE_FCA_DONE. type=%x", 1792 fct_cmd->cmd_type); 1793 1794 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 1795 /* mutex_exit(&cmd_sbp->fct_mtx); */ 1796 1797 return (FCT_FAILURE); 1798 1799 } /* emlxs_fct_send_cmd_rsp() */ 1800 1801 1802 /* COMSTAR ENTER POINT */ 1803 static fct_status_t 1804 emlxs_fct_flogi_xchg(struct fct_local_port *fct_port, struct fct_flogi_xchg *fx) 1805 { 1806 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 1807 emlxs_hba_t *hba = HBA; 1808 uint32_t size; 1809 fc_packet_t *pkt = NULL; 1810 ELS_PKT *els; 1811 fct_status_t rval = FCT_SUCCESS; 1812 1813 #ifdef FCT_API_TRACE 1814 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1815 "fct_flogi_xchg: Sending FLOGI: %p", fct_port); 1816 #else 1817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1818 "fct_flogi_xchg: Sending FLOGI."); 1819 #endif /* FCT_API_TRACE */ 1820 1821 if (hba->state <= FC_LINK_DOWN) { 1822 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1823 "fct_flogi_xchg: FLOGI failed. Link down."); 1824 rval = FCT_FAILURE; 1825 goto done; 1826 } 1827 1828 /* Use this entry point as the link up acknowledgment */ 1829 mutex_enter(&EMLXS_PORT_LOCK); 1830 port->fct_flags |= FCT_STATE_LINK_UP_ACKED; 1831 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1832 "fct_link_up acked."); 1833 mutex_exit(&EMLXS_PORT_LOCK); 1834 1835 /* First handle any pending FLOGI's */ 1836 emlxs_fct_handle_unsol_flogi(port, NULL, 0); 1837 1838 size = sizeof (SERV_PARM) + 4; 1839 1840 if (!(pkt = emlxs_pkt_alloc(port, size, size, 0, KM_NOSLEEP))) { 1841 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1842 "fct_flogi_xchg: FLOGI failed. " 1843 "Unable allocate packet."); 1844 rval = FCT_FAILURE; 1845 goto done; 1846 } 1847 1848 /* Make this a polled IO */ 1849 pkt->pkt_tran_flags &= ~FC_TRAN_INTR; 1850 pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; 1851 pkt->pkt_comp = NULL; 1852 1853 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 1854 pkt->pkt_timeout = fx->fx_sec_timeout; 1855 1856 /* Build the fc header */ 1857 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fx->fx_did); 1858 pkt->pkt_cmd_fhdr.r_ctl = 1859 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 1860 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(fx->fx_sid); 1861 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 1862 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE; 1863 pkt->pkt_cmd_fhdr.seq_id = 0; 1864 pkt->pkt_cmd_fhdr.df_ctl = 0; 1865 pkt->pkt_cmd_fhdr.seq_cnt = 0; 1866 pkt->pkt_cmd_fhdr.ox_id = 0xffff; 1867 pkt->pkt_cmd_fhdr.rx_id = 0xffff; 1868 pkt->pkt_cmd_fhdr.ro = 0; 1869 1870 /* Build the command */ 1871 /* Service paramters will be added automatically later by the driver */ 1872 els = (ELS_PKT *)pkt->pkt_cmd; 1873 els->elsCode = 0x04; /* FLOGI */ 1874 1875 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 1876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1877 "fct_flogi_xchg: FLOGI failed. " 1878 "Unable to send packet."); 1879 1880 rval = FCT_FAILURE; 1881 goto done; 1882 } 1883 1884 if ((pkt->pkt_state != FC_PKT_SUCCESS) && 1885 (pkt->pkt_state != FC_PKT_LS_RJT)) { 1886 if (pkt->pkt_state == FC_PKT_TIMEOUT) { 1887 rval = FCT_TIMEOUT; 1888 } else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) && 1889 (pkt->pkt_reason == FC_REASON_FCAL_OPN_FAIL)) { 1890 rval = FCT_NOT_FOUND; 1891 } else { 1892 rval = FCT_FAILURE; 1893 } 1894 1895 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1896 "fct_flogi_xchg: FLOGI failed. state=%x reason=%x " 1897 "rval=%llx", pkt->pkt_state, pkt->pkt_reason, rval); 1898 1899 goto done; 1900 } 1901 1902 if (pkt->pkt_state == FC_PKT_LS_RJT) { 1903 fx->fx_op = ELS_OP_LSRJT; 1904 fx->fx_rjt_reason = pkt->pkt_reason; 1905 fx->fx_rjt_expl = pkt->pkt_expln; 1906 } else { /* FC_PKT_SUCCESS */ 1907 1908 fx->fx_op = ELS_OP_ACC; 1909 fx->fx_sid = FABRIC_DID; 1910 fx->fx_did = port->did; 1911 1912 els = (ELS_PKT *)pkt->pkt_resp; 1913 bcopy((caddr_t)&els->un.logi.nodeName, 1914 (caddr_t)fx->fx_nwwn, 8); 1915 bcopy((caddr_t)&els->un.logi.portName, 1916 (caddr_t)fx->fx_pwwn, 8); 1917 fx->fx_fport = els->un.logi.cmn.fPort; 1918 } 1919 1920 done: 1921 if (pkt) { 1922 emlxs_pkt_free(pkt); 1923 } 1924 1925 if ((rval == FCT_SUCCESS) || (rval == FCT_NOT_FOUND)) { 1926 1927 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 1928 "fct_flogi_xchg: FCT_STATE_FLOGI_CMPL. rval=%s", 1929 ((rval == FCT_SUCCESS)? "FCT_SUCCESS":"FCT_NOT_FOUND")); 1930 1931 mutex_enter(&EMLXS_PORT_LOCK); 1932 port->fct_flags |= FCT_STATE_FLOGI_CMPL; 1933 mutex_exit(&EMLXS_PORT_LOCK); 1934 1935 /* 1936 * Flush all unsolicited commands 1937 * Must use separate thread since 1938 * this thread must complete first 1939 */ 1940 emlxs_thread_spawn(hba, emlxs_fct_unsol_flush_thread, 1941 (void *)port, 0); 1942 } 1943 1944 return (rval); 1945 1946 } /* emlxs_fct_flogi_xchg() */ 1947 1948 1949 /* COMSTAR ENTER POINT */ 1950 /* This is called right after we report that link has come online */ 1951 static fct_status_t 1952 emlxs_fct_get_link_info(fct_local_port_t *fct_port, fct_link_info_t *link) 1953 { 1954 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 1955 emlxs_hba_t *hba = HBA; 1956 1957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 1958 "fct_get_link_info %p: FCT: flg x%x HBA: ste x%x flg x%x topo x%x", 1959 fct_port, port->fct_flags, hba->state, hba->flag, hba->topology); 1960 1961 mutex_enter(&EMLXS_PORT_LOCK); 1962 1963 if (port->mode == MODE_INITIATOR) { 1964 link->port_topology = PORT_TOPOLOGY_UNKNOWN; 1965 link->port_speed = PORT_SPEED_UNKNOWN; 1966 link->portid = 0; 1967 1968 mutex_exit(&EMLXS_PORT_LOCK); 1969 1970 return (FCT_SUCCESS); 1971 } 1972 1973 if (!(port->fct_flags & FCT_STATE_LINK_UP) || 1974 (hba->state < FC_LINK_UP) || (hba->flag & FC_LOOPBACK_MODE)) { 1975 link->port_topology = PORT_TOPOLOGY_UNKNOWN; 1976 link->port_speed = PORT_SPEED_UNKNOWN; 1977 link->portid = 0; 1978 1979 mutex_exit(&EMLXS_PORT_LOCK); 1980 1981 return (FCT_SUCCESS); 1982 } 1983 1984 if (hba->topology == TOPOLOGY_LOOP) { 1985 link->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP; 1986 } else { 1987 link->port_topology = PORT_TOPOLOGY_PT_TO_PT; 1988 } 1989 1990 switch (hba->linkspeed) { 1991 case LA_1GHZ_LINK: 1992 link->port_speed = PORT_SPEED_1G; 1993 break; 1994 case LA_2GHZ_LINK: 1995 link->port_speed = PORT_SPEED_2G; 1996 break; 1997 case LA_4GHZ_LINK: 1998 link->port_speed = PORT_SPEED_4G; 1999 break; 2000 case LA_8GHZ_LINK: 2001 link->port_speed = PORT_SPEED_8G; 2002 break; 2003 case LA_10GHZ_LINK: 2004 link->port_speed = PORT_SPEED_10G; 2005 break; 2006 case LA_16GHZ_LINK: 2007 link->port_speed = PORT_SPEED_16G; 2008 break; 2009 default: 2010 link->port_speed = PORT_SPEED_UNKNOWN; 2011 break; 2012 } 2013 2014 link->portid = port->did; 2015 link->port_no_fct_flogi = 0; 2016 link->port_fca_flogi_done = 0; 2017 link->port_fct_flogi_done = 0; 2018 2019 mutex_exit(&EMLXS_PORT_LOCK); 2020 2021 return (FCT_SUCCESS); 2022 2023 } /* emlxs_fct_get_link_info() */ 2024 2025 2026 /* COMSTAR ENTER POINT */ 2027 static fct_status_t 2028 emlxs_fct_register_remote_port(fct_local_port_t *fct_port, 2029 fct_remote_port_t *remote_port, fct_cmd_t *fct_cmd) 2030 { 2031 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 2032 emlxs_hba_t *hba = HBA; 2033 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2034 clock_t timeout; 2035 int32_t pkt_ret; 2036 fct_els_t *els; 2037 SERV_PARM *sp; 2038 emlxs_node_t *ndlp; 2039 SERV_PARM sparam; 2040 uint32_t *iptr; 2041 uint16_t hdl; 2042 uint64_t addr; 2043 fct_status_t rval; 2044 fct_status_t rval2; 2045 uint32_t i; 2046 2047 #ifdef FCT_API_TRACE 2048 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2049 "fct_register_remote_port %p", fct_port); 2050 #endif /* FCT_API_TRACE */ 2051 2052 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 2053 2054 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, 2055 EMLXS_FCT_REG_PENDING); 2056 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2057 2058 cmd_sbp->channel = &hba->chan[hba->channel_els]; 2059 cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD; 2060 2061 } else { 2062 2063 rval = emlxs_fct_cmd_accept(port, fct_cmd, 2064 EMLXS_FCT_REG_PENDING); 2065 if (rval) { 2066 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2067 "fct_register_remote_port: " 2068 "Unable to accept fct_cmd. lid=%x rid=%x", 2069 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid); 2070 2071 return (rval); 2072 } 2073 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2074 } 2075 2076 cmd_sbp->fct_flags &= ~EMLXS_FCT_REGISTERED; 2077 cmd_sbp->node = emlxs_node_find_did(port, fct_cmd->cmd_rportid, 1); 2078 2079 /* Check for unsolicited PLOGI */ 2080 if (cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED) { 2081 els = (fct_els_t *)fct_cmd->cmd_specific; 2082 sp = (SERV_PARM *)((caddr_t)els->els_req_payload + 2083 sizeof (uint32_t)); 2084 2085 } else { /* Solicited PLOGI */ 2086 2087 sp = &sparam; 2088 bcopy((caddr_t)&port->sparam, (caddr_t)sp, 2089 sizeof (SERV_PARM)); 2090 2091 /* 2092 * Create temporary WWN's from fct_cmd address 2093 * This simply allows us to get an RPI from the 2094 * adapter until we get real service params. 2095 * The PLOGI ACC reply will trigger a REG_LOGIN 2096 * update later 2097 */ 2098 addr = (uint64_t)((unsigned long)fct_cmd); 2099 2100 iptr = (uint32_t *)&sp->portName; 2101 iptr[0] = PADDR_HI(addr); 2102 iptr[1] = PADDR_LO(addr); 2103 2104 iptr = (uint32_t *)&sp->nodeName; 2105 iptr[0] = PADDR_HI(addr); 2106 iptr[1] = PADDR_LO(addr); 2107 } 2108 2109 if (hba->flag & FC_PT_TO_PT) { 2110 mutex_enter(&EMLXS_PORT_LOCK); 2111 port->did = fct_cmd->cmd_lportid; 2112 port->rdid = fct_cmd->cmd_rportid; 2113 mutex_exit(&EMLXS_PORT_LOCK); 2114 2115 /* 2116 * We already received the remote port's 2117 * parameters in the FLOGI exchange 2118 */ 2119 if (!(cmd_sbp->fct_flags & EMLXS_FCT_PLOGI_RECEIVED)) { 2120 sp = &sparam; 2121 bcopy((caddr_t)&port->fabric_sparam, (caddr_t)sp, 2122 sizeof (SERV_PARM)); 2123 2124 /* 2125 * Since this is a PLOGI, not a FLOGI, we need 2126 * to fix up word2 of the CSP accordingly. 2127 */ 2128 sp->cmn.w2.r_a_tov = port->sparam.cmn.w2.r_a_tov; 2129 } 2130 } 2131 2132 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 2133 "fct_register_remote_port: Register lid=%x rid=%x. (%x,%x,%p)", 2134 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid, cmd_sbp->fct_state, 2135 hba->flag, fct_cmd); 2136 2137 emlxs_fct_cmd_release(port, fct_cmd, 0); 2138 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2139 2140 /* Create a new node */ 2141 if (EMLXS_SLI_REG_DID(port, fct_cmd->cmd_rportid, sp, cmd_sbp, 2142 NULL, NULL) != 0) { 2143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2144 "fct_register_remote_port: " 2145 "Reg login failed. lid=%x rid=%x", 2146 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid); 2147 } else { 2148 2149 /* Wait for completion */ 2150 mutex_enter(&EMLXS_PKT_LOCK); 2151 timeout = emlxs_timeout(hba, 30); 2152 pkt_ret = 0; 2153 while ((pkt_ret != -1) && 2154 (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) && 2155 !(cmd_sbp->fct_flags & EMLXS_FCT_REGISTERED)) { 2156 pkt_ret = cv_timedwait(&EMLXS_PKT_CV, 2157 &EMLXS_PKT_LOCK, timeout); 2158 } 2159 mutex_exit(&EMLXS_PKT_LOCK); 2160 } 2161 2162 /* Reacquire ownership of the fct_cmd */ 2163 rval2 = emlxs_fct_cmd_acquire(port, fct_cmd, 2164 EMLXS_FCT_REG_COMPLETE); 2165 if (rval2) { 2166 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2167 "fct_register_remote_port: " 2168 "Unable to reacquire fct_cmd. lid=%x rid=%x", 2169 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid); 2170 2171 return (rval2); 2172 } 2173 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2174 2175 /* Prepare response */ 2176 2177 ndlp = (emlxs_node_t *)cmd_sbp->node; 2178 2179 if (ndlp) { 2180 cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED; 2181 2182 *((emlxs_node_t **)remote_port->rp_fca_private) = 2183 cmd_sbp->node; 2184 2185 hdl = ndlp->nlp_Rpi; 2186 if (hdl == FABRIC_RPI) { 2187 if (fct_cmd->cmd_rportid == SCR_DID) { 2188 /* The SCR handle is hardcoded */ 2189 remote_port->rp_handle = hba->max_nodes; 2190 port->fct_els_only_bmap |= 1; 2191 2192 } else { 2193 for (i = 1; i < EMLXS_FCT_NUM_ELS_ONLY; i++) { 2194 if (port->fct_els_only_bmap & (1 << i)) 2195 continue; 2196 /* 2197 * Bit is not set, so use this 2198 * for the handle 2199 */ 2200 remote_port->rp_handle = 2201 hba->max_nodes + i; 2202 port->fct_els_only_bmap |= (1 << i); 2203 break; 2204 } 2205 if (i >= EMLXS_FCT_NUM_ELS_ONLY) { 2206 remote_port->rp_handle = 2207 FCT_HANDLE_NONE; 2208 } 2209 } 2210 } else { 2211 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2212 hdl = emlxs_sli4_rpi_to_index(hba, hdl); 2213 } 2214 remote_port->rp_handle = hdl; 2215 } 2216 2217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2218 "fct_register_remote_port: lid=%x rid=%x hdl=%x", 2219 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid, 2220 remote_port->rp_handle); 2221 2222 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2223 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2224 2225 TGTPORTSTAT.FctPortRegister++; 2226 return (FCT_SUCCESS); 2227 } else { 2228 *((emlxs_node_t **)remote_port->rp_fca_private) = NULL; 2229 2230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2231 "fct_register_remote_port: failed. lid=%x rid=%x hdl=%x", 2232 fct_cmd->cmd_lportid, fct_cmd->cmd_rportid, 2233 remote_port->rp_handle); 2234 2235 remote_port->rp_handle = FCT_HANDLE_NONE; 2236 2237 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2238 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2239 2240 TGTPORTSTAT.FctFailedPortRegister++; 2241 return (FCT_FAILURE); 2242 } 2243 2244 } /* emlxs_fct_register_remote_port() */ 2245 2246 2247 /* COMSTAR ENTER POINT */ 2248 static fct_status_t 2249 emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port, 2250 fct_remote_port_t *remote_port) 2251 { 2252 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 2253 emlxs_hba_t *hba = HBA; 2254 emlxs_node_t *ndlp; 2255 uint32_t i; 2256 2257 #ifdef FCT_API_TRACE 2258 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2259 "fct_deregister_remote_port: did=%x hdl=%x", 2260 remote_port->rp_id, remote_port->rp_handle); 2261 #else 2262 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2263 "fct_deregister_remote_port: did=%x hdl=%x", 2264 remote_port->rp_id, remote_port->rp_handle); 2265 #endif /* FCT_API_TRACE */ 2266 2267 if (remote_port->rp_handle >= hba->max_nodes) { 2268 i = remote_port->rp_handle - hba->max_nodes; 2269 if ((i < EMLXS_FCT_NUM_ELS_ONLY) && 2270 (port->fct_els_only_bmap & (1 << i))) { 2271 port->fct_els_only_bmap &= ~(1 << i); 2272 } 2273 } 2274 2275 ndlp = *((emlxs_node_t **)remote_port->rp_fca_private); 2276 *((emlxs_node_t **)remote_port->rp_fca_private) = NULL; 2277 2278 if (ndlp) { 2279 (void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL, 2280 NULL, NULL); 2281 } 2282 2283 TGTPORTSTAT.FctPortDeregister++; 2284 return (FCT_SUCCESS); 2285 2286 } /* emlxs_fct_deregister_remote_port() */ 2287 2288 2289 /* ARGSUSED */ 2290 extern int 2291 emlxs_fct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 2292 MATCHMAP *mp, uint32_t size) 2293 { 2294 emlxs_hba_t *hba = HBA; 2295 IOCB *iocb; 2296 fct_cmd_t *fct_cmd; 2297 emlxs_buf_t *cmd_sbp; 2298 emlxs_fcp_cmd_t *fcp_cmd; 2299 emlxs_node_t *ndlp; 2300 uint32_t cnt; 2301 uint32_t tm; 2302 uint16_t hdl; 2303 scsi_task_t *fct_task; 2304 uint8_t lun[8]; 2305 uint32_t sid = 0; 2306 2307 iocb = &iocbq->iocb; 2308 ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG); 2309 if (!ndlp) { 2310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2311 "FCP rcvd: Unknown RPI. rpi=%d rxid=%x. Dropping...", 2312 iocb->ULPIOTAG, iocb->ULPCONTEXT); 2313 2314 goto dropped; 2315 } 2316 sid = ndlp->nlp_DID; 2317 2318 fcp_cmd = (emlxs_fcp_cmd_t *)mp->virt; 2319 2320 if (!port->fct_port) { 2321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2322 "FCP rcvd: Target unbound. rpi=%d rxid=%x. Dropping...", 2323 iocb->ULPIOTAG, iocb->ULPCONTEXT); 2324 2325 emlxs_send_logo(port, sid); 2326 2327 goto dropped; 2328 } 2329 2330 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 2331 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2332 "FCP rcvd: Target offline. rpi=%d rxid=%x. Dropping...", 2333 iocb->ULPIOTAG, iocb->ULPCONTEXT); 2334 2335 emlxs_send_logo(port, sid); 2336 2337 goto dropped; 2338 } 2339 2340 /* Get lun id */ 2341 bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8); 2342 2343 if (TGTPORTSTAT.FctOutstandingIO >= port->fct_port->port_max_xchges) { 2344 TGTPORTSTAT.FctOverQDepth++; 2345 } 2346 2347 hdl = ndlp->nlp_Rpi; 2348 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2349 hdl = emlxs_sli4_rpi_to_index(hba, hdl); 2350 } 2351 fct_cmd = 2352 MODSYM(fct_scsi_task_alloc) (port->fct_port, hdl, sid, lun, 16, 0); 2353 2354 if (fct_cmd == NULL) { 2355 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2356 "FCP rcvd: sid=%x xid=%x. " 2357 "Unable to allocate scsi task. Returning QFULL.", 2358 sid, iocb->ULPCONTEXT); 2359 2360 (void) emlxs_fct_send_qfull_reply(port, ndlp, iocb->ULPCONTEXT, 2361 iocb->ULPCLASS, fcp_cmd); 2362 2363 goto dropped; 2364 } 2365 2366 /* Initialize fct_cmd */ 2367 fct_cmd->cmd_rportid = sid; 2368 fct_cmd->cmd_lportid = port->did; 2369 fct_cmd->cmd_rp_handle = hdl; 2370 fct_cmd->cmd_port = port->fct_port; 2371 2372 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_FCP_CMD_RECEIVED); 2373 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2374 2375 #ifdef FCT_API_TRACE 2376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2377 "fct_scsi_task_alloc %p:%p FCP rcvd: " 2378 "cmd=%x sid=%x rxid=%x oxid=%x lun=%02x%02x dl=%d", 2379 fct_cmd, cmd_sbp, fcp_cmd->fcpCdb[0], sid, iocb->ULPCONTEXT, 2380 iocb->unsli3.ext_rcv.oxid, lun[0], lun[1], 2381 LE_SWAP32(fcp_cmd->fcpDl)); 2382 #endif /* FCT_API_TRACE */ 2383 2384 /* Initialize cmd_sbp */ 2385 cmd_sbp->channel = cp; 2386 cmd_sbp->class = iocb->ULPCLASS; 2387 cmd_sbp->lun = (lun[0] << 8) | lun[1]; 2388 cmd_sbp->fct_type = EMLXS_FCT_FCP_CMD; 2389 cmd_sbp->ticks = hba->timer_tics + (2 * hba->fc_ratov); 2390 2391 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2392 /* xrip was setup / passed in from the SLI layer */ 2393 cmd_sbp->xrip = iocbq->sbp; 2394 cmd_sbp->node = iocbq->node; 2395 iocbq->sbp = 0; 2396 2397 fct_cmd->cmd_oxid = cmd_sbp->xrip->rx_id; 2398 fct_cmd->cmd_rxid = cmd_sbp->xrip->XRI; 2399 2400 #ifdef FCT_API_TRACE 2401 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2402 "FCP rcvd: oxid=%x rxid=%x iotag=%d %p ", 2403 fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp->xrip->iotag, 2404 hba->fc_table[cmd_sbp->xrip->iotag]); 2405 #endif /* FCT_API_TRACE */ 2406 2407 } else { 2408 fct_cmd->cmd_oxid = iocb->unsli3.ext_rcv.oxid; 2409 if (!fct_cmd->cmd_oxid) { 2410 fct_cmd->cmd_oxid = 0xFFFF; 2411 } 2412 fct_cmd->cmd_rxid = iocb->ULPCONTEXT; 2413 } 2414 2415 2416 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 2417 2418 /* Set task_flags */ 2419 switch (fcp_cmd->fcpCntl1) { 2420 case SIMPLE_Q: 2421 fct_task->task_flags = TF_ATTR_SIMPLE_QUEUE; 2422 break; 2423 2424 case HEAD_OF_Q: 2425 fct_task->task_flags = TF_ATTR_HEAD_OF_QUEUE; 2426 break; 2427 2428 case ORDERED_Q: 2429 fct_task->task_flags = TF_ATTR_ORDERED_QUEUE; 2430 break; 2431 2432 case ACA_Q: 2433 fct_task->task_flags = TF_ATTR_ACA; 2434 break; 2435 2436 case UNTAGGED: 2437 fct_task->task_flags = TF_ATTR_UNTAGGED; 2438 break; 2439 } 2440 2441 cnt = LE_SWAP32(fcp_cmd->fcpDl); 2442 switch (fcp_cmd->fcpCntl3) { 2443 case 0: 2444 TGTPORTSTAT.FctIOCmdCnt++; 2445 break; 2446 case 1: 2447 EMLXS_BUMP_WRIOCTR(port, cnt); 2448 TGTPORTSTAT.FctWriteBytes += cnt; 2449 fct_task->task_flags |= TF_WRITE_DATA; 2450 break; 2451 2452 case 2: 2453 EMLXS_BUMP_RDIOCTR(port, cnt); 2454 TGTPORTSTAT.FctReadBytes += cnt; 2455 fct_task->task_flags |= TF_READ_DATA; 2456 break; 2457 } 2458 2459 fct_task->task_priority = 0; 2460 2461 /* task_mgmt_function */ 2462 tm = fcp_cmd->fcpCntl2; 2463 if (tm) { 2464 if (tm & BIT_1) { 2465 fct_task->task_mgmt_function = TM_ABORT_TASK_SET; 2466 } else if (tm & BIT_2) { 2467 fct_task->task_mgmt_function = TM_CLEAR_TASK_SET; 2468 } else if (tm & BIT_4) { 2469 fct_task->task_mgmt_function = TM_LUN_RESET; 2470 } else if (tm & BIT_5) { 2471 fct_task->task_mgmt_function = TM_TARGET_COLD_RESET; 2472 } else if (tm & BIT_6) { 2473 fct_task->task_mgmt_function = TM_CLEAR_ACA; 2474 } else { 2475 fct_task->task_mgmt_function = TM_ABORT_TASK; 2476 } 2477 } 2478 2479 /* Parallel buffers support - future */ 2480 fct_task->task_max_nbufs = 1; 2481 2482 fct_task->task_additional_flags = 0; 2483 fct_task->task_cur_nbufs = 0; 2484 fct_task->task_csn_size = 8; 2485 fct_task->task_cmd_seq_no = 0; 2486 fct_task->task_expected_xfer_length = cnt; 2487 bcopy((void *)&fcp_cmd->fcpCdb, fct_task->task_cdb, 16); 2488 2489 TGTPORTSTAT.FctCmdReceived++; 2490 TGTPORTSTAT.FctOutstandingIO++; 2491 2492 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2493 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2494 2495 #ifdef FCT_API_TRACE 2496 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2497 "fct_post_rcvd_cmd:3 %p:%p portid x%x, %d outio %d", 2498 fct_cmd, cmd_sbp, fct_cmd->cmd_lportid, 2499 fct_task->task_expected_xfer_length, 2500 TGTPORTSTAT.FctOutstandingIO); 2501 #endif /* FCT_API_TRACE */ 2502 2503 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 2504 2505 return (0); 2506 2507 dropped: 2508 2509 TGTPORTSTAT.FctRcvDropped++; 2510 return (1); 2511 2512 } /* emlxs_fct_handle_unsol_req() */ 2513 2514 2515 /* COMSTAR ENTER POINT */ 2516 /* ARGSUSED */ 2517 static fct_status_t 2518 emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf, 2519 uint32_t ioflags) 2520 { 2521 emlxs_port_t *port = 2522 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 2523 emlxs_hba_t *hba = HBA; 2524 emlxs_buf_t *cmd_sbp; 2525 #ifdef FCT_API_TRACE 2526 scsi_task_t *fct_task; 2527 #endif /* FCT_API_TRACE */ 2528 IOCBQ *iocbq; 2529 emlxs_node_t *ndlp; 2530 2531 int channel; 2532 int channelno; 2533 fct_status_t rval = 0; 2534 2535 rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA); 2536 if (rval) { 2537 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2538 "fct_send_fcp_data: " 2539 "Unable to accept fct_cmd. did=%x", 2540 fct_cmd->cmd_rportid); 2541 2542 return (rval); 2543 } 2544 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2545 2546 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2547 #ifdef FCT_API_TRACE 2548 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 2549 #endif /* FCT_API_TRACE */ 2550 ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 2551 2552 cmd_sbp->node = ndlp; 2553 cmd_sbp->fct_buf = dbuf; 2554 2555 channelno = ((CHANNEL *)cmd_sbp->channel)->channelno; 2556 2557 channel = channelno; 2558 2559 2560 2561 iocbq = &cmd_sbp->iocbq; 2562 iocbq->sbp = cmd_sbp; 2563 2564 #ifdef FCT_API_TRACE 2565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2566 "fct_send_fcp_data %p:%p flgs=%x ioflags=%x dl=%d,%d,%d,%d", 2567 fct_cmd, cmd_sbp, dbuf->db_flags, ioflags, 2568 fct_task->task_cmd_xfer_length, 2569 fct_task->task_nbytes_transferred, dbuf->db_data_size, 2570 fct_task->task_expected_xfer_length); 2571 #endif /* FCT_API_TRACE */ 2572 2573 /* Setup for I/O prep routine */ 2574 iocbq->iocb.ULPCOMMAND = 0; 2575 2576 if (EMLXS_SLI_PREP_FCT_IOCB(port, cmd_sbp, channel) != IOERR_SUCCESS) { 2577 2578 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2579 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2580 2581 return (FCT_BUSY); 2582 } 2583 2584 cmd_sbp->fct_type = EMLXS_FCT_FCP_DATA; 2585 2586 if (dbuf->db_flags & DB_SEND_STATUS_GOOD) { 2587 cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS; 2588 } 2589 2590 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 2591 if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) { 2592 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2593 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2594 2595 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2596 emlxs_sli4_free_xri(port, cmd_sbp, 0, 0); 2597 } 2598 return (FCT_BUSY); 2599 } 2600 } 2601 2602 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 2603 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING); 2604 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2605 2606 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq); 2607 2608 return (FCT_SUCCESS); 2609 2610 } /* emlxs_fct_send_fcp_data() */ 2611 2612 2613 /* cmd_sbp->fct_mtx must be held to enter */ 2614 /* cmd_sbp->fct_mtx must be released before exiting */ 2615 static fct_status_t 2616 emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd) 2617 { 2618 emlxs_port_t *port = 2619 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 2620 emlxs_hba_t *hba = HBA; 2621 emlxs_buf_t *cmd_sbp; 2622 scsi_task_t *fct_task; 2623 fc_packet_t *pkt; 2624 emlxs_buf_t *sbp = NULL; 2625 emlxs_fcp_rsp *fcp_rsp; 2626 emlxs_node_t *ndlp; 2627 fct_status_t rval; 2628 uint32_t did; 2629 uint32_t size; 2630 2631 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 2632 ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 2633 did = fct_cmd->cmd_rportid; 2634 2635 /* Initialize cmd_sbp */ 2636 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2637 2638 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS); 2639 2640 cmd_sbp->node = ndlp; 2641 2642 size = 24; 2643 if (fct_task->task_sense_length) { 2644 size += fct_task->task_sense_length; 2645 } 2646 #ifdef FCT_API_TRACE 2647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2648 "fct_send_fcp_status %p:%p stat=%d resid=%d size=%d rx=%x ox=%x", 2649 fct_cmd, cmd_sbp, fct_task->task_scsi_status, 2650 fct_task->task_resid, size, fct_cmd->cmd_rxid, fct_cmd->cmd_oxid); 2651 #endif /* FCT_API_TRACE */ 2652 2653 if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) { 2654 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2655 "fct_send_fcp_status: Unable to allocate packet."); 2656 2657 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2658 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2659 2660 return (FCT_BUSY); 2661 } 2662 2663 cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS; 2664 2665 sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt); 2666 cmd_sbp->fct_pkt = pkt; 2667 2668 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2669 pkt->pkt_timeout = 2670 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 2671 pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout; 2672 pkt->pkt_comp = emlxs_fct_pkt_comp; 2673 2674 /* Build the fc header */ 2675 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 2676 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 2677 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 2678 pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP; 2679 pkt->pkt_cmd_fhdr.f_ctl = 2680 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2681 pkt->pkt_cmd_fhdr.seq_id = 0; 2682 pkt->pkt_cmd_fhdr.df_ctl = 0; 2683 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2684 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 2685 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 2686 pkt->pkt_cmd_fhdr.ro = 0; 2687 2688 /* Build the status payload */ 2689 fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd; 2690 2691 if (fct_task->task_resid) { 2692 if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) { 2693 TGTPORTSTAT.FctScsiResidOver++; 2694 fcp_rsp->rspStatus2 |= RESID_OVER; 2695 fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid); 2696 2697 } else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) { 2698 TGTPORTSTAT.FctScsiResidUnder++; 2699 fcp_rsp->rspStatus2 |= RESID_UNDER; 2700 fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid); 2701 2702 } 2703 } 2704 2705 if (fct_task->task_scsi_status) { 2706 if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) { 2707 TGTPORTSTAT.FctScsiQfullErr++; 2708 } else { 2709 TGTPORTSTAT.FctScsiStatusErr++; 2710 } 2711 2712 /* Make sure residual reported on non-SCSI_GOOD READ status */ 2713 if ((fct_task->task_flags & TF_READ_DATA) && 2714 (fcp_rsp->rspResId == 0)) { 2715 fcp_rsp->rspStatus2 |= RESID_UNDER; 2716 fcp_rsp->rspResId = 2717 fct_task->task_expected_xfer_length; 2718 } 2719 } 2720 2721 2722 if (fct_task->task_sense_length) { 2723 TGTPORTSTAT.FctScsiSenseErr++; 2724 fcp_rsp->rspStatus2 |= SNS_LEN_VALID; 2725 fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length); 2726 2727 bcopy((uint8_t *)fct_task->task_sense_data, 2728 (uint8_t *)&fcp_rsp->rspInfo0, 2729 fct_task->task_sense_length); 2730 } 2731 2732 fcp_rsp->rspStatus3 = fct_task->task_scsi_status; 2733 fcp_rsp->rspRspLen = 0; 2734 2735 #ifdef FCT_API_TRACE 2736 emlxs_data_dump(port, "RESP", (uint32_t *)fcp_rsp, 36, 0); 2737 #endif /* FCT_API_TRACE */ 2738 2739 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 2740 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING); 2741 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2742 2743 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 2744 2745 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2746 "fct_send_fcp_status: Unable to send packet."); 2747 2748 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2749 emlxs_sli4_free_xri(port, sbp, 0, 0); 2750 } 2751 2752 /* Reacquire ownership of the fct_cmd */ 2753 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 2754 if (rval) { 2755 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2756 "fct_send_fcp_status: " 2757 "Unable to acquire fct_cmd."); 2758 return (rval); 2759 } 2760 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2761 2762 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2763 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2764 2765 return (FCT_BUSY); 2766 } 2767 2768 return (FCT_SUCCESS); 2769 2770 } /* emlxs_fct_send_fcp_status() */ 2771 2772 2773 static fct_status_t 2774 emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp, 2775 uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd) 2776 { 2777 emlxs_hba_t *hba = HBA; 2778 emlxs_buf_t *sbp; 2779 fc_packet_t *pkt; 2780 emlxs_fcp_rsp *fcp_rsp; 2781 uint32_t size; 2782 CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT]; 2783 uint8_t lun[8]; 2784 2785 bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8); 2786 size = 24; 2787 2788 if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) { 2789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2790 "fct_send_qfull_reply: Unable to allocate packet."); 2791 return (FCT_FAILURE); 2792 } 2793 2794 sbp = PKT2PRIV(pkt); 2795 sbp->node = ndlp; 2796 sbp->channel = cp; 2797 sbp->did = ndlp->nlp_DID; 2798 sbp->lun = (lun[0] << 8) | lun[1]; 2799 sbp->class = class; 2800 2801 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2802 pkt->pkt_timeout = 2803 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 2804 2805 /* Build the fc header */ 2806 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID); 2807 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 2808 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 2809 pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP; 2810 pkt->pkt_cmd_fhdr.f_ctl = 2811 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2812 pkt->pkt_cmd_fhdr.seq_id = 0; 2813 pkt->pkt_cmd_fhdr.df_ctl = 0; 2814 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2815 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 2816 pkt->pkt_cmd_fhdr.rx_id = xid; 2817 pkt->pkt_cmd_fhdr.ro = 0; 2818 2819 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2820 "fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d", 2821 xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO, 2822 port->fct_port->port_max_xchges); 2823 2824 /* Build the status payload */ 2825 fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd; 2826 2827 TGTPORTSTAT.FctScsiQfullErr++; 2828 fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL; 2829 fcp_rsp->rspStatus2 |= RESID_UNDER; 2830 fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl); 2831 2832 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 2833 2834 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2835 emlxs_sli4_free_xri(port, sbp, 0, 0); 2836 } 2837 2838 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2839 "fct_send_qfull_reply: Unable to send packet."); 2840 emlxs_pkt_free(pkt); 2841 return (FCT_FAILURE); 2842 } 2843 2844 return (FCT_SUCCESS); 2845 2846 } /* emlxs_fct_send_qfull_reply() */ 2847 2848 2849 /* ARGSUSED */ 2850 extern int 2851 emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2852 { 2853 emlxs_port_t *port = &PPORT; 2854 IOCB *iocb; 2855 emlxs_buf_t *sbp; 2856 emlxs_buf_t *cmd_sbp; 2857 uint32_t status; 2858 fct_cmd_t *fct_cmd; 2859 stmf_data_buf_t *dbuf; 2860 scsi_task_t *fct_task; 2861 fc_packet_t *pkt; 2862 uint32_t fct_flags; 2863 stmf_data_buf_t *fct_buf; 2864 fct_status_t rval; 2865 2866 iocb = &iocbq->iocb; 2867 sbp = (emlxs_buf_t *)iocbq->sbp; 2868 2869 TGTPORTSTAT.FctEvent++; 2870 2871 if (!sbp) { 2872 /* completion with missing xmit command */ 2873 TGTPORTSTAT.FctStray++; 2874 2875 /* emlxs_stray_fcp_completion_msg */ 2876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2877 "FCP event cmd=%x status=%x error=%x iotag=%d", 2878 iocb->ULPCOMMAND, iocb->ULPSTATUS, 2879 iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG); 2880 2881 return (1); 2882 } 2883 2884 TGTPORTSTAT.FctCompleted++; 2885 2886 port = sbp->iocbq.port; 2887 fct_cmd = sbp->fct_cmd; 2888 status = iocb->ULPSTATUS; 2889 2890 #ifdef FCT_API_TRACE 2891 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2892 "fct_handle_fcp_event: %p:%p cmd=%x status=%x, %x", 2893 fct_cmd, sbp, iocb->ULPCOMMAND, status, iocb->ULPCT); 2894 #endif /* FCT_API_TRACE */ 2895 2896 if (fct_cmd == NULL) { 2897 /* For driver generated QFULL response */ 2898 if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) || 2899 (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) { 2900 emlxs_pkt_free(sbp->pkt); 2901 } 2902 return (0); 2903 } 2904 2905 rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE); 2906 if (rval) { 2907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2908 "fct_handle_fcp_event: " 2909 "Unable to reacquire fct_cmd. type=%x", 2910 fct_cmd->cmd_type); 2911 2912 return (1); 2913 } 2914 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2915 2916 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2917 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 2918 2919 pkt = cmd_sbp->fct_pkt; 2920 cmd_sbp->fct_pkt = NULL; 2921 2922 dbuf = sbp->fct_buf; 2923 2924 fct_cmd->cmd_comp_status = FCT_SUCCESS; 2925 2926 if (status) { 2927 emlxs_dma_error: 2928 /* 2929 * The error indicates this IO should be terminated 2930 * immediately. 2931 */ 2932 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 2933 fct_cmd->cmd_comp_status = FCT_FAILURE; 2934 2935 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 2936 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2937 2938 #ifdef FCT_API_TRACE 2939 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2940 "fct_queue_cmd_for_termination:1 %p: x%x", 2941 fct_cmd, fct_cmd->cmd_comp_status); 2942 #endif /* FCT_API_TRACE */ 2943 2944 MODSYM(fct_queue_cmd_for_termination) (fct_cmd, 2945 FCT_ABTS_RECEIVED); 2946 2947 goto done; 2948 } 2949 2950 switch (iocb->ULPCOMMAND) { 2951 2952 /* 2953 * FCP Data completion 2954 */ 2955 case CMD_FCP_TSEND_CX: 2956 case CMD_FCP_TSEND64_CX: 2957 case CMD_FCP_TRECEIVE_CX: 2958 case CMD_FCP_TRECEIVE64_CX: 2959 2960 if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) { 2961 if (emlxs_fct_dbuf_dma_sync(hba, dbuf, 2962 DDI_DMA_SYNC_FORCPU)) { 2963 goto emlxs_dma_error; 2964 } 2965 } 2966 2967 if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) && 2968 (iocb->ULPCT != 1)) { 2969 2970 dbuf->db_flags |= DB_STATUS_GOOD_SENT; 2971 2972 fct_task = 2973 (scsi_task_t *)fct_cmd->cmd_specific; 2974 fct_task->task_scsi_status = 0; 2975 2976 (void) emlxs_fct_send_fcp_status(fct_cmd); 2977 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2978 2979 break; 2980 2981 } else if ((cmd_sbp->fct_flags & 2982 EMLXS_FCT_SEND_STATUS) && 2983 (iocb->ULPCT == 1)) { 2984 /* Auto-resp has been sent out by firmware */ 2985 /* We can assume this is really a FC_TRSP_CX */ 2986 2987 dbuf->db_flags |= DB_STATUS_GOOD_SENT; 2988 fct_task = 2989 (scsi_task_t *)fct_cmd->cmd_specific; 2990 fct_task->task_scsi_status = 0; 2991 2992 cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS; 2993 2994 goto auto_resp; 2995 } 2996 2997 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 2998 2999 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 3000 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3001 3002 #ifdef FCT_API_TRACE 3003 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3004 "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf); 3005 #endif /* FCT_API_TRACE */ 3006 3007 MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0); 3008 3009 break; 3010 3011 /* FCP Status completion */ 3012 case CMD_FCP_TRSP_CX: 3013 case CMD_FCP_TRSP64_CX: 3014 3015 auto_resp: 3016 /* Copy these before calling emlxs_fct_cmd_done */ 3017 fct_flags = cmd_sbp->fct_flags; 3018 fct_buf = cmd_sbp->fct_buf; 3019 3020 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3021 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3022 3023 TGTPORTSTAT.FctOutstandingIO--; 3024 3025 if (fct_flags & EMLXS_FCT_SEND_STATUS) { 3026 #ifdef FCT_API_TRACE 3027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3028 "fct_scsi_data_xfer_done:2 %p %p outio %d", 3029 fct_cmd, fct_buf, TGTPORTSTAT.FctOutstandingIO); 3030 #endif /* FCT_API_TRACE */ 3031 3032 MODSYM(fct_scsi_data_xfer_done) (fct_cmd, 3033 fct_buf, FCT_IOF_FCA_DONE); 3034 } else { 3035 #ifdef FCT_API_TRACE 3036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3037 "fct_send_response_done:1 %p: x%x outio %d", 3038 fct_cmd, fct_cmd->cmd_comp_status, 3039 TGTPORTSTAT.FctOutstandingIO); 3040 #endif /* FCT_API_TRACE */ 3041 3042 MODSYM(fct_send_response_done) (fct_cmd, 3043 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3044 } 3045 break; 3046 3047 default: 3048 emlxs_fct_cmd_release(port, fct_cmd, 0); 3049 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3050 3051 TGTPORTSTAT.FctStray++; 3052 TGTPORTSTAT.FctCompleted--; 3053 3054 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3055 "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND); 3056 3057 if (pkt) { 3058 emlxs_pkt_complete(sbp, status, 3059 iocb->un.grsp.perr.statLocalError, 1); 3060 } 3061 3062 } /* switch(iocb->ULPCOMMAND) */ 3063 3064 3065 done: 3066 if (pkt) { 3067 emlxs_pkt_free(pkt); 3068 } 3069 3070 if (status == IOSTAT_SUCCESS) { 3071 TGTPORTSTAT.FctCmplGood++; 3072 } else { 3073 TGTPORTSTAT.FctCmplError++; 3074 } 3075 3076 return (0); 3077 3078 } /* emlxs_fct_handle_fcp_event() */ 3079 3080 3081 /* ARGSUSED */ 3082 extern int 3083 emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 3084 { 3085 emlxs_port_t *port = &PPORT; 3086 IOCB *iocb; 3087 emlxs_buf_t *sbp; 3088 fc_packet_t *pkt; 3089 3090 iocb = &iocbq->iocb; 3091 sbp = (emlxs_buf_t *)iocbq->sbp; 3092 3093 TGTPORTSTAT.FctEvent++; 3094 3095 if (!sbp) { 3096 /* completion with missing xmit command */ 3097 TGTPORTSTAT.FctStray++; 3098 3099 /* emlxs_stray_fcp_completion_msg */ 3100 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3101 "ABORT event cmd=%x status=%x error=%x iotag=%d", 3102 iocb->ULPCOMMAND, iocb->ULPSTATUS, 3103 iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG); 3104 3105 return (1); 3106 } 3107 3108 pkt = PRIV2PKT(sbp); 3109 3110 #ifdef FCT_API_TRACE 3111 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3112 "fct_handle_abort: %p:%p xri=%d cmd=%x status=%x", 3113 sbp->fct_cmd, sbp, 3114 iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS); 3115 #endif /* FCT_API_TRACE */ 3116 3117 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3118 XRIobj_t *xrip; 3119 3120 emlxs_sli4_free_xri(port, NULL, sbp->xrip, 1); 3121 xrip = emlxs_sli4_find_xri(port, iocb->ULPCONTEXT); 3122 if (!xrip || xrip->state == XRI_STATE_FREE) { 3123 goto exit; 3124 } 3125 3126 if ((hba->fc_table[xrip->iotag]) && 3127 (hba->fc_table[xrip->iotag] != STALE_PACKET)) { 3128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 3129 "Cmd not aborted, retrying: xri=%d iotag=%d sbp=%p", 3130 xrip->XRI, xrip->iotag, hba->fc_table[xrip->iotag]); 3131 3132 /* Abort retry */ 3133 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 3134 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_debug_msg, 3135 "Abort retry failed xri=%x", xrip->XRI); 3136 } else { 3137 return (0); 3138 } 3139 } 3140 } 3141 3142 exit: 3143 if (pkt) { 3144 emlxs_pkt_free(pkt); 3145 } 3146 return (0); 3147 3148 } /* emlxs_fct_handle_abort() */ 3149 3150 3151 extern int 3152 emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3153 MATCHMAP *mp, uint32_t size) 3154 { 3155 emlxs_hba_t *hba = HBA; 3156 IOCB *iocb; 3157 uint32_t cmd_code; 3158 fct_cmd_t *fct_cmd; 3159 fct_els_t *els; 3160 uint32_t sid; 3161 uint32_t padding; 3162 uint8_t *bp; 3163 emlxs_buf_t *cmd_sbp; 3164 uint32_t rval; 3165 3166 HBASTATS.ElsCmdReceived++; 3167 3168 bp = mp->virt; 3169 cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK; 3170 iocb = &iocbq->iocb; 3171 sid = iocb->un.elsreq.remoteID; 3172 3173 if (!port->fct_port) { 3174 if (!(hba->flag & FC_ONLINE_MODE)) { 3175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3176 "%s: sid=%x. Adapter offline. Dropping...", 3177 emlxs_elscmd_xlate(cmd_code), sid); 3178 goto done; 3179 } 3180 3181 switch (cmd_code) { 3182 case ELS_CMD_LOGO: 3183 case ELS_CMD_PRLO: 3184 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3185 "%s: sid=%x. Target unbound. Accepting...", 3186 emlxs_elscmd_xlate(cmd_code), sid); 3187 (void) emlxs_els_reply(port, iocbq, ELS_CMD_ACC, 3188 ELS_CMD_LOGO, 0, 0); 3189 break; 3190 default: 3191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3192 "%s: sid=%x. Target unbound. Rejecting...", 3193 emlxs_elscmd_xlate(cmd_code), sid); 3194 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, 3195 cmd_code, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 3196 break; 3197 } 3198 goto done; 3199 } 3200 3201 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 3202 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3203 "%s: sid=%x. Target offline. Rejecting...", 3204 emlxs_elscmd_xlate(cmd_code), sid); 3205 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, 3206 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 3207 3208 goto done; 3209 } 3210 3211 #ifdef FCT_API_TRACE 3212 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3213 "%s: sid=%x cnt=%d. Target rcv. ", 3214 emlxs_elscmd_xlate(cmd_code), sid, size); 3215 #endif /* FCT_API_TRACE */ 3216 3217 /* Process the request */ 3218 switch (cmd_code) { 3219 case ELS_CMD_FLOGI: 3220 rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size); 3221 3222 if (!rval) { 3223 ELS_PKT *els_pkt = (ELS_PKT *)bp; 3224 fct_flogi_xchg_t fx; 3225 3226 bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t)); 3227 3228 /* Save the FLOGI exchange information */ 3229 fx.rsvd2 = iocb->ULPCONTEXT; 3230 bcopy((caddr_t)&els_pkt->un.logi.nodeName, 3231 (caddr_t)fx.fx_nwwn, 8); 3232 bcopy((caddr_t)&els_pkt->un.logi.portName, 3233 (caddr_t)fx.fx_pwwn, 8); 3234 fx.fx_sid = sid; 3235 fx.fx_did = iocb->un.elsreq.myID; 3236 fx.fx_fport = els_pkt->un.logi.cmn.fPort; 3237 fx.fx_op = ELS_OP_FLOGI; 3238 3239 emlxs_fct_handle_unsol_flogi(port, &fx, 1); 3240 } 3241 3242 goto done; 3243 3244 case ELS_CMD_PLOGI: 3245 rval = 3246 emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size); 3247 break; 3248 3249 default: 3250 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3251 "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid); 3252 rval = 0; 3253 break; 3254 } 3255 3256 if (rval) { 3257 goto done; 3258 } 3259 3260 padding = (8 - (size & 7)) & 7; 3261 3262 fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS, 3263 (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)), 3264 AF_FORCE_NOSLEEP); 3265 3266 #ifdef FCT_API_TRACE 3267 { 3268 uint32_t *ptr = (uint32_t *)bp; 3269 3270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3271 "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x", 3272 fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1)); 3273 } 3274 #endif /* FCT_API_TRACE */ 3275 3276 if (fct_cmd == NULL) { 3277 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3278 "%s: sid=%x. Out of memory. Rejecting...", 3279 emlxs_elscmd_xlate(cmd_code), sid); 3280 3281 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, 3282 LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE); 3283 goto done; 3284 } 3285 3286 /* Initialize fct_cmd */ 3287 fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff; 3288 fct_cmd->cmd_rxid = iocb->ULPCONTEXT; 3289 fct_cmd->cmd_rportid = sid; 3290 fct_cmd->cmd_lportid = port->did; 3291 fct_cmd->cmd_rp_handle = FCT_HANDLE_NONE; 3292 fct_cmd->cmd_port = port->fct_port; 3293 3294 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED); 3295 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3296 3297 /* Initialize cmd_sbp */ 3298 cmd_sbp->channel = cp; 3299 cmd_sbp->class = iocb->ULPCLASS; 3300 cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD; 3301 cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED; 3302 3303 bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq, 3304 sizeof (emlxs_iocb_t)); 3305 3306 els = (fct_els_t *)fct_cmd->cmd_specific; 3307 els->els_req_size = (uint16_t)size; 3308 els->els_req_payload = 3309 GET_BYTE_OFFSET(fct_cmd->cmd_fca_private, 3310 GET_STRUCT_SIZE(emlxs_buf_t)); 3311 bcopy(bp, els->els_req_payload, size); 3312 3313 3314 /* Check if Offline */ 3315 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 3316 3317 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 3318 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3319 3320 #ifdef FCT_API_TRACE 3321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3322 "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd, 3323 fct_cmd->cmd_lportid); 3324 #endif /* FCT_API_TRACE */ 3325 3326 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 3327 3328 goto done; 3329 } 3330 3331 /* Online */ 3332 3333 /* Check if Link up is acked */ 3334 if (!(port->fct_flags & FCT_STATE_LINK_UP_ACKED)) { 3335 goto defer; 3336 } 3337 3338 if ((cmd_code != ELS_CMD_FLOGI) && 3339 !(port->fct_flags & FCT_STATE_FLOGI_CMPL)) { 3340 goto defer; 3341 } 3342 3343 /* Post it to COMSTAR */ 3344 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 3345 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3346 3347 #ifdef FCT_API_TRACE 3348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3349 "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd, 3350 fct_cmd->cmd_lportid); 3351 #endif /* FCT_API_TRACE */ 3352 3353 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 3354 3355 goto done; 3356 3357 defer: 3358 /* Defer processing of fct_cmd till later (after link up ack). */ 3359 3360 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3361 "%s: sid=%x. Defer Processing x%x.", 3362 emlxs_elscmd_xlate(cmd_code), sid, port->fct_flags); 3363 3364 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ); 3365 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3366 3367 /* Add cmd_sbp to queue tail */ 3368 mutex_enter(&EMLXS_PORT_LOCK); 3369 3370 if (port->fct_wait_tail) { 3371 port->fct_wait_tail->next = cmd_sbp; 3372 } 3373 port->fct_wait_tail = cmd_sbp; 3374 3375 if (!port->fct_wait_head) { 3376 port->fct_wait_head = cmd_sbp; 3377 } 3378 3379 mutex_exit(&EMLXS_PORT_LOCK); 3380 3381 done: 3382 3383 return (0); 3384 3385 } /* emlxs_fct_handle_unsol_els() */ 3386 3387 3388 /* ARGSUSED */ 3389 static uint32_t 3390 emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3391 MATCHMAP *mp, uint32_t size) 3392 { 3393 IOCB *iocb; 3394 char buffer[64]; 3395 3396 buffer[0] = 0; 3397 3398 iocb = &iocbq->iocb; 3399 3400 /* Perform processing of FLOGI payload */ 3401 if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer, 3402 sizeof (buffer))) { 3403 return (1); 3404 } 3405 3406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3407 "FLOGI: sid=0x%x xid=%x %s", 3408 iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer); 3409 3410 return (0); 3411 3412 } /* emlxs_fct_process_unsol_flogi() */ 3413 3414 3415 /* ARGSUSED */ 3416 static uint32_t 3417 emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3418 MATCHMAP *mp, uint32_t size) 3419 { 3420 IOCB *iocb; 3421 char buffer[64]; 3422 3423 buffer[0] = 0; 3424 3425 iocb = &iocbq->iocb; 3426 3427 /* Perform processing of PLOGI payload */ 3428 if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer, 3429 sizeof (buffer))) { 3430 return (1); 3431 } 3432 3433 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3434 "PLOGI: sid=0x%x xid=%x %s", 3435 iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer); 3436 3437 return (0); 3438 3439 } /* emlxs_fct_process_unsol_plogi() */ 3440 3441 3442 /* ARGSUSED */ 3443 static emlxs_buf_t * 3444 emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3445 fc_packet_t *pkt) 3446 { 3447 emlxs_buf_t *cmd_sbp; 3448 emlxs_buf_t *sbp; 3449 3450 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3451 3452 sbp = PKT2PRIV(pkt); 3453 sbp->fct_cmd = cmd_sbp->fct_cmd; 3454 sbp->node = cmd_sbp->node; 3455 sbp->channel = cmd_sbp->channel; 3456 sbp->did = cmd_sbp->did; 3457 sbp->lun = cmd_sbp->lun; 3458 sbp->class = cmd_sbp->class; 3459 sbp->fct_type = cmd_sbp->fct_type; 3460 sbp->fct_state = cmd_sbp->fct_state; 3461 sbp->xrip = cmd_sbp->xrip; 3462 sbp->iotag = cmd_sbp->iotag; 3463 3464 return (sbp); 3465 3466 } /* emlxs_fct_pkt_init() */ 3467 3468 3469 /* Mutex will be acquired */ 3470 static emlxs_buf_t * 3471 emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) 3472 { 3473 emlxs_hba_t *hba = HBA; 3474 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3475 3476 bzero((void *)cmd_sbp, sizeof (emlxs_buf_t)); 3477 mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER, 3478 DDI_INTR_PRI(hba->intr_arg)); 3479 mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, 3480 DDI_INTR_PRI(hba->intr_arg)); 3481 3482 mutex_enter(&cmd_sbp->fct_mtx); 3483 cmd_sbp->pkt_flags = PACKET_VALID; 3484 cmd_sbp->port = port; 3485 cmd_sbp->fct_cmd = fct_cmd; 3486 cmd_sbp->node = (fct_cmd->cmd_rp) ? 3487 *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL; 3488 cmd_sbp->iocbq.sbp = cmd_sbp; 3489 cmd_sbp->iocbq.port = port; 3490 cmd_sbp->did = fct_cmd->cmd_rportid; 3491 3492 /* Flags fct_cmd as inuse */ 3493 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3494 fct_cmd->cmd_oxid = 0xffff; 3495 fct_cmd->cmd_rxid = 0xffff; 3496 } 3497 3498 if (fct_state) { 3499 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3500 } 3501 3502 return (cmd_sbp); 3503 3504 } /* emlxs_fct_cmd_init() */ 3505 3506 3507 /* Called after receiving fct_cmd from COMSTAR */ 3508 static fct_status_t 3509 emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) 3510 { 3511 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3512 3513 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3515 "fct_cmd_accept: " 3516 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3517 fct_cmd, fct_state); 3518 3519 return (FCT_NOT_FOUND); 3520 } 3521 3522 mutex_enter(&cmd_sbp->fct_mtx); 3523 3524 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3525 mutex_exit(&cmd_sbp->fct_mtx); 3526 3527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3528 "fct_cmd_accept:2 " 3529 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3530 fct_cmd, fct_state); 3531 3532 return (FCT_NOT_FOUND); 3533 } 3534 3535 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 3536 3537 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3538 "fct_cmd_accept: " 3539 "Aborted fct_cmd found! fct_cmd=%p state=%x", 3540 fct_cmd, fct_state); 3541 3542 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE); 3543 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3544 3545 MODSYM(fct_cmd_fca_aborted) (fct_cmd, 3546 FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 3547 3548 return (FCT_NOT_FOUND); 3549 } 3550 3551 mutex_enter(&cmd_sbp->mtx); 3552 if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3553 mutex_exit(&cmd_sbp->mtx); 3554 mutex_exit(&cmd_sbp->fct_mtx); 3555 3556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3557 "fct_cmd_accept: " 3558 "Busy fct_cmd found! fct_cmd=%p state=%x", 3559 fct_cmd, fct_state); 3560 3561 return (FCT_BUSY); 3562 } 3563 cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED; 3564 mutex_exit(&cmd_sbp->mtx); 3565 3566 if (fct_state) { 3567 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3568 } 3569 3570 return (FCT_SUCCESS); 3571 3572 } /* emlxs_fct_cmd_accept() */ 3573 3574 3575 /* Called after receiving fct_cmd from driver */ 3576 static fct_status_t 3577 emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3578 uint16_t fct_state) 3579 { 3580 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3581 3582 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3583 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3584 "fct_cmd_acquire: " 3585 "Bad fct_cmd found! fct_cmd=%p state=%x", 3586 fct_cmd, fct_state); 3587 3588 return (FCT_NOT_FOUND); 3589 } 3590 3591 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3592 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3593 "fct_cmd_acquire: " 3594 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3595 fct_cmd, fct_state); 3596 3597 return (FCT_NOT_FOUND); 3598 } 3599 3600 if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3601 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3602 "fct_cmd_acquire: " 3603 "Returned fct_cmd found! fct_cmd=%p state=%x", 3604 fct_cmd, fct_state); 3605 3606 return (FCT_NOT_FOUND); 3607 } 3608 3609 mutex_enter(&cmd_sbp->fct_mtx); 3610 3611 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3612 mutex_exit(&cmd_sbp->fct_mtx); 3613 3614 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3615 "fct_cmd_acquire:2 " 3616 "Bad fct_cmd found! fct_cmd=%p state=%x", 3617 fct_cmd, fct_state); 3618 3619 return (FCT_NOT_FOUND); 3620 } 3621 3622 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3623 mutex_exit(&cmd_sbp->fct_mtx); 3624 3625 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3626 "fct_cmd_acquire:2 " 3627 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3628 fct_cmd, fct_state); 3629 3630 return (FCT_NOT_FOUND); 3631 } 3632 3633 if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3634 mutex_exit(&cmd_sbp->fct_mtx); 3635 3636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3637 "fct_cmd_acquire:2 " 3638 "Returned fct_cmd found! fct_cmd=%p state=%x", 3639 fct_cmd, fct_state); 3640 3641 return (FCT_NOT_FOUND); 3642 } 3643 3644 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 3645 3646 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3647 "fct_cmd_acquire: " 3648 "Aborting cmd. fct_cmd=%p state=%x", 3649 fct_cmd, fct_state); 3650 3651 if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) { 3652 TGTPORTSTAT.FctOutstandingIO--; 3653 } 3654 3655 fct_cmd->cmd_comp_status = FCT_FAILURE; 3656 3657 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE); 3658 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3659 3660 MODSYM(fct_cmd_fca_aborted) (fct_cmd, 3661 FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 3662 3663 return (FCT_NOT_FOUND); 3664 } 3665 3666 if (fct_state) { 3667 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3668 } 3669 3670 return (FCT_SUCCESS); 3671 3672 } /* emlxs_fct_cmd_acquire() */ 3673 3674 3675 /* cmd_sbp->fct_mtx must be held to enter */ 3676 /* cmd_sbp->fct_mtx must be released before exiting */ 3677 /* Called before transitionally sending fct_cmd to driver */ 3678 /*ARGSUSED*/ 3679 static void 3680 emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3681 uint16_t fct_state) 3682 { 3683 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3684 3685 if (fct_state) { 3686 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3687 } 3688 3689 mutex_exit(&cmd_sbp->fct_mtx); 3690 3691 return; 3692 3693 } /* emlxs_fct_cmd_release() */ 3694 3695 3696 /* cmd_sbp->fct_mtx must be held to enter */ 3697 /* cmd_sbp->fct_mtx must be released before exiting */ 3698 /* Called before posting fct_cmd back to COMSTAR */ 3699 /*ARGSUSED*/ 3700 static void 3701 emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3702 uint16_t fct_state) 3703 { 3704 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3705 fc_packet_t *pkt; 3706 3707 pkt = cmd_sbp->fct_pkt; 3708 cmd_sbp->fct_pkt = NULL; 3709 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3710 3711 mutex_enter(&cmd_sbp->mtx); 3712 cmd_sbp->pkt_flags |= PACKET_ULP_OWNED; 3713 mutex_exit(&cmd_sbp->mtx); 3714 3715 if (fct_state) { 3716 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3717 } 3718 3719 mutex_exit(&cmd_sbp->fct_mtx); 3720 3721 if (pkt) { 3722 emlxs_pkt_free(pkt); 3723 } 3724 3725 return; 3726 3727 } /* emlxs_fct_cmd_post() */ 3728 3729 3730 /* cmd_sbp->fct_mtx must be held to enter */ 3731 /* Called before completing fct_cmd back to COMSTAR */ 3732 static void 3733 emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) 3734 { 3735 emlxs_hba_t *hba = HBA; 3736 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3737 fc_packet_t *pkt; 3738 3739 /* Flags fct_cmd is no longer used */ 3740 fct_cmd->cmd_oxid = 0; 3741 fct_cmd->cmd_rxid = 0; 3742 3743 if (cmd_sbp->iotag != 0) { 3744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3745 "Pkt still registered! channel=%p iotag=%d sbp=%p", 3746 cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp); 3747 3748 if (cmd_sbp->channel) { 3749 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3750 emlxs_sli4_free_xri(port, cmd_sbp, 3751 cmd_sbp->xrip, 1); 3752 } else { 3753 (void) emlxs_unregister_pkt(cmd_sbp->channel, 3754 cmd_sbp->iotag, 0); 3755 } 3756 3757 } 3758 } 3759 3760 pkt = cmd_sbp->fct_pkt; 3761 cmd_sbp->fct_pkt = NULL; 3762 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3763 3764 if (fct_state) { 3765 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3766 } 3767 3768 mutex_enter(&cmd_sbp->mtx); 3769 cmd_sbp->pkt_flags |= PACKET_ULP_OWNED; 3770 cmd_sbp->pkt_flags &= ~PACKET_VALID; 3771 mutex_exit(&cmd_sbp->mtx); 3772 mutex_exit(&cmd_sbp->fct_mtx); 3773 3774 3775 mutex_destroy(&cmd_sbp->fct_mtx); 3776 mutex_destroy(&cmd_sbp->mtx); 3777 3778 if (pkt) { 3779 emlxs_pkt_free(pkt); 3780 } 3781 3782 return; 3783 3784 } /* emlxs_fct_cmd_done() */ 3785 3786 3787 static void 3788 emlxs_fct_pkt_comp(fc_packet_t *pkt) 3789 { 3790 emlxs_port_t *port; 3791 #ifdef FMA_SUPPORT 3792 emlxs_hba_t *hba; 3793 #endif /* FMA_SUPPORT */ 3794 emlxs_buf_t *sbp; 3795 emlxs_buf_t *cmd_sbp; 3796 fct_cmd_t *fct_cmd; 3797 fct_els_t *fct_els; 3798 fct_sol_ct_t *fct_ct; 3799 fct_status_t rval; 3800 3801 sbp = PKT2PRIV(pkt); 3802 port = sbp->port; 3803 #ifdef FMA_SUPPORT 3804 hba = HBA; 3805 #endif /* FMA_SUPPORT */ 3806 fct_cmd = sbp->fct_cmd; 3807 3808 rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE); 3809 if (rval) { 3810 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3811 "fct_pkt_comp: " 3812 "Unable to reacquire fct_cmd."); 3813 return; 3814 } 3815 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3816 3817 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3818 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3819 cmd_sbp->fct_pkt = NULL; 3820 3821 switch (fct_cmd->cmd_type) { 3822 case FCT_CMD_FCP_XCHG: 3823 if ((pkt->pkt_reason == FC_REASON_ABORTED) || 3824 (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) || 3825 (pkt->pkt_reason == FC_REASON_OFFLINE)) { 3826 /* 3827 * The error indicates this IO should be terminated 3828 * immediately. 3829 */ 3830 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 3831 3832 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 3833 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3834 3835 #ifdef FCT_API_TRACE 3836 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3837 "fct_queue_cmd_for_termination:2 %p:%p x%x", 3838 fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status); 3839 #endif /* FCT_API_TRACE */ 3840 3841 MODSYM(fct_queue_cmd_for_termination) (fct_cmd, 3842 FCT_ABTS_RECEIVED); 3843 3844 break; 3845 } 3846 3847 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3848 EMLXS_FCT_PKT_FCPRSP_COMPLETE); 3849 3850 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3851 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3852 3853 #ifdef FCT_API_TRACE 3854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3855 "fct_send_response_done:2 %p:%p x%x outio %d", 3856 fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status, 3857 TGTPORTSTAT.FctOutstandingIO); 3858 #else 3859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3860 "fct_pkt_comp: fct_send_response_done. dbuf=%p", 3861 sbp->fct_buf); 3862 #endif /* FCT_API_TRACE */ 3863 3864 TGTPORTSTAT.FctOutstandingIO--; 3865 3866 MODSYM(fct_send_response_done) (fct_cmd, 3867 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3868 3869 break; 3870 3871 case FCT_CMD_RCVD_ELS: 3872 3873 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3874 EMLXS_FCT_PKT_ELSRSP_COMPLETE); 3875 3876 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3877 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3878 3879 #ifdef FCT_API_TRACE 3880 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3881 "fct_send_response_done:3 %p:%p x%x", 3882 fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status); 3883 #endif /* FCT_API_TRACE */ 3884 3885 MODSYM(fct_send_response_done) (fct_cmd, 3886 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3887 3888 break; 3889 3890 case FCT_CMD_SOL_ELS: 3891 3892 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3893 EMLXS_FCT_PKT_ELSCMD_COMPLETE); 3894 3895 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 3896 3897 if (fct_els->els_resp_payload) { 3898 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, 3899 pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL); 3900 3901 bcopy((uint8_t *)pkt->pkt_resp, 3902 (uint8_t *)fct_els->els_resp_payload, 3903 fct_els->els_resp_size); 3904 } 3905 3906 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3907 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3908 3909 #ifdef FCT_API_TRACE 3910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3911 "fct_send_cmd_done:1 %p:%p x%x", 3912 fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status); 3913 #endif /* FCT_API_TRACE */ 3914 3915 #ifdef FMA_SUPPORT 3916 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) 3917 != DDI_FM_OK) { 3918 EMLXS_MSGF(EMLXS_CONTEXT, 3919 &emlxs_invalid_dma_handle_msg, 3920 "fct_pkt_comp: hdl=%p", 3921 pkt->pkt_resp_dma); 3922 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE, 3923 FCT_IOF_FCA_DONE); 3924 3925 break; 3926 } 3927 #endif /* FMA_SUPPORT */ 3928 3929 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, 3930 FCT_IOF_FCA_DONE); 3931 3932 break; 3933 3934 case FCT_CMD_SOL_CT: 3935 3936 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3937 EMLXS_FCT_PKT_CTCMD_COMPLETE); 3938 3939 fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific; 3940 3941 if (fct_ct->ct_resp_payload) { 3942 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, 3943 pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL); 3944 3945 bcopy((uint8_t *)pkt->pkt_resp, 3946 (uint8_t *)fct_ct->ct_resp_payload, 3947 fct_ct->ct_resp_size); 3948 } 3949 3950 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3951 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3952 3953 #ifdef FCT_API_TRACE 3954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3955 "fct_send_cmd_done:2 %p:%p x%x", 3956 fct_cmd, cmd_sbp, fct_cmd->cmd_comp_status); 3957 #endif /* FCT_API_TRACE */ 3958 3959 #ifdef FMA_SUPPORT 3960 if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) 3961 != DDI_FM_OK) { 3962 EMLXS_MSGF(EMLXS_CONTEXT, 3963 &emlxs_invalid_dma_handle_msg, 3964 "fct_pkt_comp: hdl=%p", 3965 pkt->pkt_resp_dma); 3966 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE, 3967 FCT_IOF_FCA_DONE); 3968 3969 break; 3970 } 3971 #endif /* FMA_SUPPORT */ 3972 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, 3973 FCT_IOF_FCA_DONE); 3974 3975 break; 3976 3977 default: 3978 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3979 "fct_pkt_comp: Invalid cmd type found. type=%x", 3980 fct_cmd->cmd_type); 3981 3982 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3983 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3984 3985 break; 3986 } 3987 3988 emlxs_pkt_free(pkt); 3989 return; 3990 3991 } /* emlxs_fct_pkt_comp() */ 3992 3993 3994 static void 3995 emlxs_fct_abort_pkt_comp(fc_packet_t *pkt) 3996 { 3997 #ifdef FCT_API_TRACE 3998 emlxs_buf_t *sbp; 3999 IOCBQ *iocbq; 4000 IOCB *iocb; 4001 emlxs_port_t *port; 4002 4003 sbp = PKT2PRIV(pkt); 4004 port = sbp->port; 4005 iocbq = &sbp->iocbq; 4006 iocb = &iocbq->iocb; 4007 4008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4009 "fct_abort_pkt_comp: %p: xri=%d cmd=%x status=%x", 4010 sbp->fct_cmd, sbp, 4011 iocb->ULPCONTEXT, iocb->ULPCOMMAND, iocb->ULPSTATUS); 4012 #endif /* FCT_API_TRACE */ 4013 4014 emlxs_pkt_free(pkt); 4015 return; 4016 4017 } /* emlxs_fct_abort_pkt_comp() */ 4018 4019 4020 /* COMSTAR ENTER POINT (INDIRECT) */ 4021 static fct_status_t 4022 emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd) 4023 { 4024 emlxs_port_t *port = 4025 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 4026 emlxs_hba_t *hba = HBA; 4027 uint32_t did; 4028 uint32_t sid; 4029 fct_els_t *fct_els; 4030 fc_packet_t *pkt; 4031 emlxs_buf_t *cmd_sbp; 4032 fct_status_t rval; 4033 4034 did = fct_cmd->cmd_rportid; 4035 sid = fct_cmd->cmd_lportid; 4036 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 4037 4038 if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size, 4039 fct_els->els_resp_size, 0, KM_NOSLEEP))) { 4040 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4041 "fct_send_els_cmd: Unable to allocate packet."); 4042 4043 return (FCT_BUSY); 4044 } 4045 4046 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ); 4047 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4048 4049 cmd_sbp->channel = &hba->chan[hba->channel_els]; 4050 cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ; 4051 4052 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 4053 cmd_sbp->fct_pkt = pkt; 4054 4055 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 4056 pkt->pkt_timeout = 4057 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4058 pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout; 4059 pkt->pkt_comp = emlxs_fct_pkt_comp; 4060 4061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4062 "fct_send_els_cmd: pkt_timeout=%d ratov=%d", 4063 pkt->pkt_timeout, hba->fc_ratov); 4064 4065 /* Build the fc header */ 4066 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 4067 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ; 4068 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid); 4069 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 4070 pkt->pkt_cmd_fhdr.f_ctl = 4071 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 4072 pkt->pkt_cmd_fhdr.seq_id = 0; 4073 pkt->pkt_cmd_fhdr.df_ctl = 0; 4074 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4075 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 4076 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 4077 pkt->pkt_cmd_fhdr.ro = 0; 4078 4079 /* Copy the cmd payload */ 4080 bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd, 4081 fct_els->els_req_size); 4082 4083 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 4084 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING); 4085 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4086 4087 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4088 4089 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4090 "fct_send_els_cmd: Unable to send packet."); 4091 4092 /* Reacquire ownership of the fct_cmd */ 4093 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 4094 if (rval) { 4095 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4096 "fct_send_els_cmd: " 4097 "Unable to reacquire fct_cmd."); 4098 return (rval); 4099 } 4100 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4101 4102 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 4103 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4104 4105 return (FCT_BUSY); 4106 } 4107 4108 return (FCT_SUCCESS); 4109 4110 } /* emlxs_fct_send_els_cmd() */ 4111 4112 4113 /* cmd_sbp->fct_mtx must be held to enter */ 4114 /* cmd_sbp->fct_mtx must be released before exiting */ 4115 static fct_status_t 4116 emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd) 4117 { 4118 emlxs_port_t *port = 4119 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 4120 emlxs_hba_t *hba = HBA; 4121 uint32_t did; 4122 uint32_t sid; 4123 fct_els_t *fct_els; 4124 fc_packet_t *pkt; 4125 emlxs_buf_t *cmd_sbp; 4126 fct_status_t rval; 4127 4128 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 4129 did = fct_cmd->cmd_rportid; 4130 sid = fct_cmd->cmd_lportid; 4131 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4132 4133 if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0, 4134 KM_NOSLEEP))) { 4135 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4136 "fct_send_els_rsp: Unable to allocate packet."); 4137 4138 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 4139 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4140 4141 return (FCT_FAILURE); 4142 } 4143 4144 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP); 4145 4146 cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP; 4147 4148 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 4149 cmd_sbp->fct_pkt = pkt; 4150 4151 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 4152 pkt->pkt_timeout = 4153 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4154 pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout; 4155 pkt->pkt_comp = emlxs_fct_pkt_comp; 4156 4157 /* Build the fc header */ 4158 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 4159 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP; 4160 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid); 4161 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 4162 pkt->pkt_cmd_fhdr.f_ctl = 4163 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 4164 pkt->pkt_cmd_fhdr.seq_id = 0; 4165 pkt->pkt_cmd_fhdr.df_ctl = 0; 4166 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4167 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 4168 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 4169 pkt->pkt_cmd_fhdr.ro = 0; 4170 4171 /* Copy the resp payload to pkt_cmd buffer */ 4172 bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd, 4173 fct_els->els_resp_size); 4174 4175 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 4176 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING); 4177 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4178 4179 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4180 4181 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4182 "fct_send_els_rsp: Unable to send packet."); 4183 4184 /* Reacquire ownership of the fct_cmd */ 4185 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 4186 if (rval) { 4187 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4188 "fct_send_els_rsp: " 4189 "Unable to reacquire fct_cmd."); 4190 return (rval); 4191 } 4192 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4193 4194 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 4195 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4196 4197 return (FCT_FAILURE); 4198 } 4199 4200 return (FCT_SUCCESS); 4201 4202 } /* emlxs_fct_send_els_rsp() */ 4203 4204 4205 /* COMSTAR ENTER POINT (INDIRECT) */ 4206 static fct_status_t 4207 emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd) 4208 { 4209 emlxs_port_t *port = 4210 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 4211 emlxs_hba_t *hba = HBA; 4212 uint32_t did; 4213 fct_sol_ct_t *fct_ct; 4214 fc_packet_t *pkt; 4215 emlxs_buf_t *cmd_sbp; 4216 fct_status_t rval; 4217 4218 did = fct_cmd->cmd_rportid; 4219 fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific; 4220 4221 if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size, 4222 fct_ct->ct_resp_size, 0, KM_NOSLEEP))) { 4223 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4224 "fct_send_ct_cmd: Unable to allocate packet."); 4225 return (FCT_BUSY); 4226 } 4227 4228 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ); 4229 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4230 4231 cmd_sbp->channel = &hba->chan[hba->channel_ct]; 4232 cmd_sbp->fct_type = EMLXS_FCT_CT_REQ; 4233 4234 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 4235 cmd_sbp->fct_pkt = pkt; 4236 4237 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 4238 pkt->pkt_timeout = 4239 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4240 pkt->pkt_timeout = (pkt->pkt_timeout > 60)? 60: pkt->pkt_timeout; 4241 pkt->pkt_comp = emlxs_fct_pkt_comp; 4242 4243 /* Build the fc header */ 4244 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 4245 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL; 4246 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 4247 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 4248 pkt->pkt_cmd_fhdr.f_ctl = 4249 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 4250 pkt->pkt_cmd_fhdr.seq_id = 0; 4251 pkt->pkt_cmd_fhdr.df_ctl = 0; 4252 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4253 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 4254 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 4255 pkt->pkt_cmd_fhdr.ro = 0; 4256 4257 /* Copy the cmd payload */ 4258 bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd, 4259 fct_ct->ct_req_size); 4260 4261 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 4262 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING); 4263 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4264 4265 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4266 4267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4268 "fct_send_ct_cmd: Unable to send packet."); 4269 4270 /* Reacquire ownership of the fct_cmd */ 4271 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 4272 if (rval) { 4273 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4274 "fct_send_ct_cmd: " 4275 "Unable to reacquire fct_cmd."); 4276 4277 return (rval); 4278 } 4279 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4280 4281 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 4282 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4283 4284 return (FCT_BUSY); 4285 } 4286 4287 return (FCT_SUCCESS); 4288 4289 } /* emlxs_fct_send_ct_cmd() */ 4290 4291 4292 /* cmd_sbp->fct_mtx must be held to enter */ 4293 static uint32_t 4294 emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp) 4295 { 4296 emlxs_hba_t *hba = HBA; 4297 NODELIST *nlp; 4298 fc_packet_t *pkt; 4299 emlxs_buf_t *sbp; 4300 emlxs_buf_t *iocb_sbp; 4301 uint8_t channelno; 4302 CHANNEL *cp; 4303 IOCBQ *iocbq; 4304 IOCBQ *next; 4305 IOCBQ *prev; 4306 uint32_t found; 4307 uint32_t pkt_flags; 4308 4309 /* Check the transmit queue */ 4310 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 4311 4312 /* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */ 4313 pkt = cmd_sbp->fct_pkt; 4314 if (pkt) { 4315 sbp = PKT2PRIV(pkt); 4316 if (sbp == NULL) { 4317 goto done; 4318 } 4319 iocb_sbp = sbp; 4320 iocbq = &sbp->iocbq; 4321 pkt_flags = sbp->pkt_flags; 4322 } else { 4323 sbp = NULL; 4324 iocb_sbp = cmd_sbp; 4325 iocbq = &cmd_sbp->iocbq; 4326 pkt_flags = cmd_sbp->pkt_flags; 4327 } 4328 4329 nlp = (NODELIST *)cmd_sbp->node; 4330 cp = (CHANNEL *)cmd_sbp->channel; 4331 channelno = (cp) ? cp->channelno : 0; 4332 4333 if (pkt_flags & PACKET_IN_TXQ) { 4334 /* Find it on the queue */ 4335 found = 0; 4336 if (iocbq->flag & IOCB_PRIORITY) { 4337 /* Search the priority queue */ 4338 prev = NULL; 4339 next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 4340 4341 while (next) { 4342 if (next == iocbq) { 4343 /* Remove it */ 4344 if (prev) { 4345 prev->next = iocbq->next; 4346 } 4347 4348 if (nlp->nlp_ptx[channelno].q_last == 4349 (void *)iocbq) { 4350 nlp->nlp_ptx[channelno].q_last = 4351 (void *)prev; 4352 } 4353 4354 if (nlp->nlp_ptx[channelno].q_first == 4355 (void *)iocbq) { 4356 nlp->nlp_ptx[channelno]. 4357 q_first = 4358 (void *)iocbq->next; 4359 } 4360 4361 nlp->nlp_ptx[channelno].q_cnt--; 4362 iocbq->next = NULL; 4363 found = 1; 4364 break; 4365 } 4366 4367 prev = next; 4368 next = next->next; 4369 } 4370 } else { 4371 /* Search the normal queue */ 4372 prev = NULL; 4373 next = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 4374 4375 while (next) { 4376 if (next == iocbq) { 4377 /* Remove it */ 4378 if (prev) { 4379 prev->next = iocbq->next; 4380 } 4381 4382 if (nlp->nlp_tx[channelno].q_last == 4383 (void *)iocbq) { 4384 nlp->nlp_tx[channelno].q_last = 4385 (void *)prev; 4386 } 4387 4388 if (nlp->nlp_tx[channelno].q_first == 4389 (void *)iocbq) { 4390 nlp->nlp_tx[channelno].q_first = 4391 (void *)iocbq->next; 4392 } 4393 4394 nlp->nlp_tx[channelno].q_cnt--; 4395 iocbq->next = NULL; 4396 found = 1; 4397 break; 4398 } 4399 4400 prev = next; 4401 next = (IOCBQ *)next->next; 4402 } 4403 } 4404 4405 if (!found) { 4406 goto done; 4407 } 4408 4409 /* Check if node still needs servicing */ 4410 if ((nlp->nlp_ptx[channelno].q_first) || 4411 (nlp->nlp_tx[channelno].q_first && 4412 !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 4413 4414 /* 4415 * If this is the base node, don't shift the pointers 4416 */ 4417 /* We want to drain the base node before moving on */ 4418 if (!nlp->nlp_base) { 4419 /* Shift channel queue pointers to next node */ 4420 cp->nodeq.q_last = (void *)nlp; 4421 cp->nodeq.q_first = nlp->nlp_next[channelno]; 4422 } 4423 } else { 4424 /* Remove node from channel queue */ 4425 4426 /* If this is the last node on list */ 4427 if (cp->nodeq.q_last == (void *)nlp) { 4428 cp->nodeq.q_last = NULL; 4429 cp->nodeq.q_first = NULL; 4430 cp->nodeq.q_cnt = 0; 4431 } else { 4432 /* Remove node from head */ 4433 cp->nodeq.q_first = nlp->nlp_next[channelno]; 4434 ((NODELIST *)cp->nodeq.q_last)-> 4435 nlp_next[channelno] = cp->nodeq.q_first; 4436 cp->nodeq.q_cnt--; 4437 } 4438 4439 /* Clear node */ 4440 nlp->nlp_next[channelno] = NULL; 4441 } 4442 4443 /* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */ 4444 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4445 emlxs_sli4_free_xri(port, iocb_sbp, iocb_sbp->xrip, 1); 4446 } else { 4447 (void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0); 4448 } 4449 4450 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 4451 4452 if (pkt) { 4453 emlxs_pkt_free(pkt); 4454 cmd_sbp->fct_pkt = NULL; 4455 } 4456 return (1); 4457 } 4458 done: 4459 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 4460 return (0); 4461 4462 } /* emlxs_fct_pkt_abort_txq() */ 4463 4464 4465 /* COMSTAR ENTER POINT */ 4466 /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */ 4467 /* FCT_SUCCESS indicates abort will occur asyncronously */ 4468 static fct_status_t 4469 emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd, 4470 uint32_t flags) 4471 { 4472 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 4473 emlxs_hba_t *hba = HBA; 4474 emlxs_buf_t *cmd_sbp; 4475 emlxs_buf_t *cmd_sbp2; 4476 emlxs_buf_t *prev; 4477 fc_packet_t *pkt; 4478 emlxs_buf_t *sbp = NULL; 4479 kmutex_t *fct_mtx; 4480 uint32_t fct_state; 4481 4482 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4483 fct_mtx = &cmd_sbp->fct_mtx; 4484 4485 top: 4486 4487 /* Sanity check */ 4488 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 4489 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4490 "fct_abort: Bad fct_cmd=%p.", fct_cmd); 4491 4492 return (FCT_NOT_FOUND); 4493 } 4494 4495 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 4496 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4497 "fct_abort: Pkt invalid. cmd_sbp=%p", 4498 cmd_sbp); 4499 4500 return (FCT_NOT_FOUND); 4501 } 4502 4503 if (mutex_tryenter(fct_mtx) == 0) { 4504 /* 4505 * This code path handles a race condition if 4506 * an IO completes, in emlxs_fct_handle_fcp_event(), 4507 * and we get an abort at the same time. 4508 */ 4509 delay(drv_usectohz(100000)); /* 100 msec */ 4510 goto top; 4511 } 4512 /* At this point, we have entered the mutex */ 4513 4514 /* Sanity check */ 4515 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 4516 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4517 "fct_abort: Bad fct_cmd=%p.", fct_cmd); 4518 4519 mutex_exit(fct_mtx); 4520 return (FCT_NOT_FOUND); 4521 } 4522 4523 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 4524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4525 "fct_abort: Pkt invalid. cmd_sbp=%p", 4526 cmd_sbp); 4527 4528 mutex_exit(fct_mtx); 4529 return (FCT_NOT_FOUND); 4530 } 4531 4532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4533 "fct_abort: hbastate=%x. " 4534 "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x", 4535 hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp, 4536 cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags); 4537 4538 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 4539 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0); 4540 4541 /* If Abort is already in progress */ 4542 mutex_exit(fct_mtx); 4543 return (FCT_SUCCESS); 4544 } 4545 cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP; 4546 4547 if (flags & FCT_IOF_FORCE_FCA_DONE) { 4548 fct_cmd->cmd_handle = 0; 4549 } 4550 4551 TGTPORTSTAT.FctAbortSent++; 4552 4553 switch (cmd_sbp->fct_state) { 4554 /* These are currently owned by COMSTAR. */ 4555 /* They were last processed by emlxs_fct_cmd_post() */ 4556 /* We have NO exchange resources associated with this IO. */ 4557 case EMLXS_FCT_OWNED: 4558 goto abort_done; 4559 4560 /* These are on the unsol waitQ in the driver */ 4561 case EMLXS_FCT_CMD_WAITQ: 4562 /* Find and remove it */ 4563 mutex_enter(&EMLXS_PORT_LOCK); 4564 cmd_sbp2 = port->fct_wait_head; 4565 prev = NULL; 4566 while (cmd_sbp2) { 4567 if (cmd_sbp2 == cmd_sbp) { 4568 /* Remove it */ 4569 if (prev) { 4570 prev->next = cmd_sbp2->next; 4571 } 4572 4573 if (port->fct_wait_head == cmd_sbp2) { 4574 port->fct_wait_head = cmd_sbp2->next; 4575 } 4576 4577 if (port->fct_wait_tail == cmd_sbp2) { 4578 port->fct_wait_tail = prev; 4579 } 4580 4581 cmd_sbp2->next = NULL; 4582 break; 4583 } 4584 prev = cmd_sbp2; 4585 cmd_sbp2 = cmd_sbp2->next; 4586 } 4587 mutex_exit(&EMLXS_PORT_LOCK); 4588 4589 /*FALLTHROUGH*/ 4590 4591 /* These are currently owned by COMSTAR. */ 4592 /* They were last processed by emlxs_fct_cmd_post() */ 4593 /* We have residual exchange resources associated with this IO */ 4594 case EMLXS_FCT_CMD_POSTED: 4595 switch (fct_cmd->cmd_type) { 4596 case FCT_CMD_FCP_XCHG: /* Unsol */ 4597 TGTPORTSTAT.FctOutstandingIO--; 4598 emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid); 4599 break; 4600 4601 case FCT_CMD_RCVD_ELS: /* Unsol */ 4602 emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid); 4603 break; 4604 } 4605 4606 goto abort_done; 4607 4608 /* These are active in the driver */ 4609 /* They were last processed by emlxs_fct_cmd_release() */ 4610 case EMLXS_FCT_RSP_PENDING: 4611 case EMLXS_FCT_REQ_PENDING: 4612 case EMLXS_FCT_REG_PENDING: 4613 case EMLXS_FCT_DATA_PENDING: 4614 case EMLXS_FCT_STATUS_PENDING: 4615 4616 /* Abort anything pending */ 4617 if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) { 4618 4619 if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) { 4620 TGTPORTSTAT.FctOutstandingIO--; 4621 } 4622 4623 goto abort_done; 4624 } 4625 4626 /* If we're not online, then all IO will be flushed anyway */ 4627 if (!(hba->flag & FC_ONLINE_MODE)) { 4628 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4629 "fct_abort: Not online. fct_cmd=%p.", 4630 fct_cmd); 4631 4632 emlxs_fct_cmd_release(port, fct_cmd, 0); 4633 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4634 4635 /* The cmd will be aborted on the */ 4636 /* next emlxs_fct_cmd_acquire */ 4637 /* because EMLXS_FCT_ABORT_INP is set. */ 4638 break; 4639 } 4640 4641 /* Try to send abort request */ 4642 if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) { 4643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4644 "fct_abort: Unable to allocate packet. " 4645 "fct_cmd=%p", 4646 fct_cmd); 4647 4648 emlxs_fct_cmd_release(port, fct_cmd, 0); 4649 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4650 4651 /* The cmd will be aborted on the */ 4652 /* next emlxs_fct_cmd_acquire anyway */ 4653 /* because EMLXS_FCT_ABORT_INP is set. */ 4654 break; 4655 } 4656 4657 sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt); 4658 4659 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 4660 pkt->pkt_timeout = 4661 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4662 pkt->pkt_comp = emlxs_fct_abort_pkt_comp; 4663 4664 /* Build the fc header */ 4665 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid); 4666 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 4667 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 4668 pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS; 4669 pkt->pkt_cmd_fhdr.f_ctl = 4670 (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ); 4671 pkt->pkt_cmd_fhdr.seq_id = 0; 4672 pkt->pkt_cmd_fhdr.df_ctl = 0; 4673 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4674 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 4675 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 4676 pkt->pkt_cmd_fhdr.ro = 0; 4677 4678 /* Make sure xrip is setup */ 4679 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4680 if (!sbp->xrip || sbp->xrip->state == XRI_STATE_FREE) { 4681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4682 "fct_abort: " 4683 "Unable to acquire xri. (xid:%x,%x)", 4684 fct_cmd->cmd_oxid, fct_cmd->cmd_rxid); 4685 4686 emlxs_pkt_free(pkt); 4687 return (FCT_NOT_FOUND); 4688 } 4689 } 4690 4691 cmd_sbp->fct_cmd = fct_cmd; 4692 cmd_sbp->abort_attempts++; 4693 4694 /* Now disassociate the sbp / pkt from the fct_cmd */ 4695 sbp->fct_cmd = NULL; 4696 4697 if (hba->state >= FC_LINK_UP) { 4698 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4699 "fct_abort: ABORT: %p xid:%x,%x", 4700 fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid); 4701 4702 fct_state = EMLXS_FCT_ABORT_PENDING; 4703 4704 } else { 4705 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4706 "fct_abort: CLOSE: %p xid:%x,%x", 4707 fct_cmd, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid); 4708 4709 fct_state = EMLXS_FCT_CLOSE_PENDING; 4710 } 4711 4712 emlxs_fct_cmd_release(port, fct_cmd, fct_state); 4713 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4714 4715 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4716 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4717 "fct_abort: Unable to send abort packet."); 4718 4719 emlxs_pkt_free(pkt); 4720 4721 /* The cmd will be aborted on the */ 4722 /* next emlxs_fct_cmd_acquire anyway */ 4723 /* because EMLXS_FCT_ABORT_INP is set. */ 4724 } 4725 4726 break; 4727 4728 default: 4729 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4730 "fct_abort: Unexpected fct_state. " 4731 "fct_cmd=%p state=%d", 4732 fct_cmd, cmd_sbp->fct_state); 4733 4734 emlxs_fct_cmd_release(port, fct_cmd, 0); 4735 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4736 4737 /* The cmd will be aborted on the */ 4738 /* next emlxs_fct_cmd_acquire anyway */ 4739 /* because EMLXS_FCT_ABORT_INP is set. */ 4740 4741 } /* switch */ 4742 4743 return (FCT_SUCCESS); 4744 4745 abort_done: 4746 4747 emlxs_fct_cmd_done(port, fct_cmd, 4748 EMLXS_FCT_ABORT_DONE); 4749 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4750 4751 return (FCT_ABORT_SUCCESS); 4752 4753 } /* emlxs_fct_abort() */ 4754 4755 4756 extern void 4757 emlxs_fct_link_up(emlxs_port_t *port) 4758 { 4759 emlxs_hba_t *hba = HBA; 4760 4761 mutex_enter(&EMLXS_PORT_LOCK); 4762 #ifdef FCT_API_TRACE 4763 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4764 "fct_link_up port %p fct flags x%x", 4765 port->fct_port, port->fct_flags); 4766 #endif /* FCT_API_TRACE */ 4767 4768 if (port->fct_port && 4769 (port->fct_flags & FCT_STATE_PORT_ONLINE) && 4770 !(port->fct_flags & FCT_STATE_LINK_UP)) { 4771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4772 "fct_link_up event."); 4773 4774 port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED; 4775 port->fct_flags &= ~FCT_STATE_FLOGI_CMPL; 4776 port->fct_flags |= FCT_STATE_LINK_UP; 4777 mutex_exit(&EMLXS_PORT_LOCK); 4778 4779 #ifdef FCT_API_TRACE 4780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4781 "fct_handle_event LINK_UP"); 4782 #endif /* FCT_API_TRACE */ 4783 MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP, 4784 0, 0); 4785 } else if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 4786 mutex_exit(&EMLXS_PORT_LOCK); 4787 4788 if (port->vpi == 0) { 4789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4790 "fct_link_up event. FCT port offline (%x). " 4791 "Disable link.", 4792 port->fct_flags); 4793 4794 /* Take link down and hold it down */ 4795 (void) emlxs_reset_link(hba, 0, 1); 4796 } else { 4797 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4798 "fct_link_up event. FCT port offline (%x).", 4799 port->fct_flags); 4800 } 4801 } else { 4802 mutex_exit(&EMLXS_PORT_LOCK); 4803 } 4804 4805 return; 4806 4807 } /* emlxs_fct_link_up() */ 4808 4809 4810 extern void 4811 emlxs_fct_link_down(emlxs_port_t *port) 4812 { 4813 emlxs_hba_t *hba = HBA; 4814 4815 mutex_enter(&EMLXS_PORT_LOCK); 4816 #ifdef FCT_API_TRACE 4817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4818 "fct_link_down port %p fct flags x%x", 4819 port->fct_port, port->fct_flags); 4820 #endif /* FCT_API_TRACE */ 4821 4822 if (port->fct_port && 4823 (port->fct_flags & FCT_STATE_PORT_ONLINE) && 4824 (port->fct_flags & FCT_STATE_LINK_UP)) { 4825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4826 "fct_link_down event."); 4827 4828 port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED; 4829 port->fct_flags &= ~FCT_STATE_FLOGI_CMPL; 4830 port->fct_flags &= ~FCT_STATE_LINK_UP; 4831 mutex_exit(&EMLXS_PORT_LOCK); 4832 4833 #ifdef FCT_API_TRACE 4834 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4835 "fct_handle_event LINK_DOWN"); 4836 #endif /* FCT_API_TRACE */ 4837 4838 MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN, 4839 0, 0); 4840 } else { 4841 mutex_exit(&EMLXS_PORT_LOCK); 4842 } 4843 4844 return; 4845 4846 } /* emlxs_fct_link_down() */ 4847 4848 4849 void 4850 emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) 4851 { 4852 CHANNEL *cp; 4853 IOCBQ *iocbq; 4854 IOCB *iocb; 4855 4856 if (rxid == 0 || rxid == 0xFFFF) { 4857 return; 4858 } 4859 4860 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4861 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4862 "Aborting FCT exchange: xid=%x", rxid); 4863 4864 if (emlxs_sli4_unreserve_xri(port, rxid, 1) == 0) { 4865 /* We have no way to abort unsolicited exchanges */ 4866 /* that we have not responded to at this time */ 4867 /* So we will return for now */ 4868 return; 4869 } 4870 } 4871 4872 cp = &hba->chan[hba->channel_fcp]; 4873 4874 mutex_enter(&EMLXS_FCTAB_LOCK); 4875 4876 /* Create the abort IOCB */ 4877 if (hba->state >= FC_LINK_UP) { 4878 iocbq = emlxs_create_abort_xri_cx(port, NULL, rxid, cp, 4879 CLASS3, ABORT_TYPE_ABTS); 4880 } else { 4881 iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); 4882 } 4883 4884 mutex_exit(&EMLXS_FCTAB_LOCK); 4885 4886 if (iocbq) { 4887 iocb = &iocbq->iocb; 4888 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4889 "Aborting FCT exchange: xid=%x iotag=%d", rxid, 4890 iocb->ULPIOTAG); 4891 4892 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 4893 } 4894 4895 } /* emlxs_abort_fct_exchange() */ 4896 4897 4898 extern uint32_t 4899 emlxs_fct_stmf_alloc(emlxs_hba_t *hba, MATCHMAP *mp) 4900 { 4901 emlxs_port_t *port = &PPORT; 4902 stmf_data_buf_t *db; 4903 4904 if (mp->tag < MEM_FCTSEG) { 4905 return (0); 4906 } 4907 4908 db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0); 4909 4910 #ifdef FCT_API_TRACE 4911 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4912 "stmf_alloc:%p iotag=%d phys %p virt %p sz %d", 4913 db, mp->tag, mp->phys, mp->virt, mp->size); 4914 #endif /* FCT_API_TRACE */ 4915 4916 if (db == NULL) { 4917 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4918 "emlxs_fct_stmf_alloc: alloc failed."); 4919 return (1); 4920 } 4921 4922 db->db_port_private = (void*)mp; 4923 db->db_sglist[0].seg_addr = mp->virt; 4924 db->db_sglist[0].seg_length = mp->size; 4925 db->db_buf_size = mp->size; 4926 db->db_sglist_length = 1; 4927 4928 mp->fct_private = (void*)db; 4929 4930 return (0); 4931 4932 } /* emlxs_fct_stmf_alloc() */ 4933 4934 4935 /* ARGSUSED */ 4936 extern void 4937 emlxs_fct_stmf_free(emlxs_hba_t *hba, MATCHMAP *mp) 4938 { 4939 #ifdef FCT_API_TRACE 4940 emlxs_port_t *port = &PPORT; 4941 #endif /* FCT_API_TRACE */ 4942 stmf_data_buf_t *db; 4943 4944 if (mp->tag < MEM_FCTSEG) { 4945 return; 4946 } 4947 4948 db = (stmf_data_buf_t *)mp->fct_private; 4949 mp->fct_private = NULL; 4950 4951 if (db == NULL) { 4952 return; 4953 } 4954 4955 #ifdef FCT_API_TRACE 4956 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4957 "stmf_free:%p iotag=%d", 4958 db, mp->tag); 4959 #endif /* FCT_API_TRACE */ 4960 4961 MODSYM(stmf_free) (db); 4962 4963 return; 4964 4965 } /* emlxs_fct_stmf_free() */ 4966 4967 4968 static void 4969 emlxs_fct_memseg_init(emlxs_hba_t *hba) 4970 { 4971 emlxs_port_t *port = &PPORT; 4972 char **arrayp = NULL; 4973 uint32_t cnt = 0; 4974 char buf[32]; 4975 uint32_t rval; 4976 uint8_t *datap; 4977 int i; 4978 int j; 4979 int fct_memseg_cnt = 0; 4980 int numblks; 4981 int memsize; 4982 emlxs_memseg_t *fct_memseg = NULL; 4983 uint32_t fct_memseg_size = 0; 4984 emlxs_memseg_t *current; 4985 emlxs_memseg_t *next; 4986 emlxs_memseg_t *seg; 4987 4988 port->fct_memseg = NULL; 4989 port->fct_memseg_cnt = 0; 4990 4991 /* Check for the per adapter setting */ 4992 (void) snprintf(buf, sizeof (buf), "%s%d-fct-bufpool", DRIVER_NAME, 4993 hba->ddiinst); 4994 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 4995 (DDI_PROP_DONTPASS), buf, &arrayp, &cnt); 4996 4997 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 4998 /* Check for the global setting */ 4999 cnt = 0; 5000 arrayp = NULL; 5001 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 5002 (DDI_PROP_DONTPASS), "fct-bufpool", &arrayp, &cnt); 5003 } 5004 5005 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 5006 goto default_config; 5007 } 5008 5009 fct_memseg_size = cnt * sizeof (emlxs_memseg_t); 5010 fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP); 5011 5012 if (!fct_memseg) { 5013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5014 "Unable to alloc fct_memseg. cnt=%d. " 5015 "Trying default config.", 5016 cnt); 5017 goto default_config; 5018 } 5019 5020 for (i = 0; i < cnt; i++) { 5021 datap = (uint8_t *)arrayp[i]; 5022 if (datap == 0) { 5023 break; 5024 } 5025 5026 while (*datap == ' ') { /* Skip spaces */ 5027 datap++; 5028 } 5029 5030 memsize = emlxs_str_atoi(datap); 5031 5032 while ((*datap != ':') && (*datap != 0)) { 5033 datap++; 5034 } 5035 if (*datap == ':') { /* Skip past delimeter */ 5036 datap++; 5037 } 5038 while (*datap == ' ') { /* Skip spaces */ 5039 datap++; 5040 } 5041 5042 numblks = emlxs_str_atoi(datap); 5043 5044 /* Check for a bad entry */ 5045 if (!memsize || !numblks) { 5046 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5047 "fct-bufpool: Entry %d:%d. Invalid.", 5048 memsize, numblks); 5049 continue; 5050 } 5051 5052 fct_memseg[fct_memseg_cnt].fc_memsize = memsize; 5053 fct_memseg[fct_memseg_cnt].fc_numblks = numblks; 5054 fct_memseg_cnt++; 5055 5056 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5057 "fct-bufpool: Entry:%d %d:%d", 5058 fct_memseg_cnt, memsize, numblks); 5059 } 5060 5061 if (!fct_memseg_cnt) { 5062 kmem_free(fct_memseg, fct_memseg_size); 5063 fct_memseg_size = 0; 5064 fct_memseg = NULL; 5065 } 5066 5067 default_config: 5068 /* If buffer list is empty, setup defaults */ 5069 if (!fct_memseg) { 5070 5071 fct_memseg_size = 8 * sizeof (emlxs_memseg_t); 5072 fct_memseg = kmem_zalloc(fct_memseg_size, KM_SLEEP); 5073 5074 if (!fct_memseg) { 5075 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5076 "Unable to alloc default port buffer pool. " 5077 "fct_memseg_cnt=%d", 5078 cnt); 5079 return; 5080 } 5081 5082 i = 0; 5083 numblks = FCT_BUF_COUNT_2K; 5084 if (numblks) { 5085 fct_memseg[i].fc_memsize = 2 * 1024; 5086 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_2K; 5087 } 5088 numblks = FCT_BUF_COUNT_4K; 5089 if (numblks) { 5090 fct_memseg[i].fc_memsize = 4 * 1024; 5091 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_4K; 5092 } 5093 numblks = FCT_BUF_COUNT_8K; 5094 if (numblks) { 5095 fct_memseg[i].fc_memsize = 8 * 1024; 5096 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_8K; 5097 } 5098 numblks = FCT_BUF_COUNT_16K; 5099 if (numblks) { 5100 fct_memseg[i].fc_memsize = 16 * 1024; 5101 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_16K; 5102 } 5103 numblks = FCT_BUF_COUNT_32K; 5104 if (numblks) { 5105 fct_memseg[i].fc_memsize = 32 * 1024; 5106 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_32K; 5107 } 5108 numblks = FCT_BUF_COUNT_64K; 5109 if (numblks) { 5110 fct_memseg[i].fc_memsize = 64 * 1024; 5111 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_64K; 5112 } 5113 numblks = FCT_BUF_COUNT_128K; 5114 if (numblks) { 5115 fct_memseg[i].fc_memsize = 128 * 1024; 5116 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_128K; 5117 } 5118 numblks = FCT_BUF_COUNT_256K; 5119 if (numblks) { 5120 fct_memseg[i].fc_memsize = 256 * 1024; 5121 fct_memseg[i++].fc_numblks = FCT_BUF_COUNT_256K; 5122 } 5123 fct_memseg_cnt = i; 5124 } 5125 5126 port->fct_memseg = kmem_zalloc((fct_memseg_cnt * 5127 sizeof (emlxs_memseg_t)), KM_SLEEP); 5128 5129 if (!port->fct_memseg) { 5130 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5131 "Unable to alloc port buffer pool. fct_memseg_cnt=%d", 5132 fct_memseg_cnt); 5133 kmem_free(fct_memseg, fct_memseg_size); 5134 return; 5135 } 5136 5137 /* Initalize port bucket list */ 5138 port->fct_memseg_cnt = fct_memseg_cnt; 5139 5140 /* Sort the entries smallest to largest */ 5141 seg = port->fct_memseg; 5142 for (i = 0; i < fct_memseg_cnt; i++, seg++) { 5143 5144 /* Find next smallest buffer */ 5145 current = fct_memseg; 5146 next = NULL; 5147 for (j = 0; j < fct_memseg_cnt; j++, current++) { 5148 if (current->fc_memsize == 0) { 5149 continue; 5150 } 5151 5152 if (next == NULL) { 5153 next = current; 5154 continue; 5155 } 5156 5157 if (current->fc_memsize < next->fc_memsize) { 5158 next = current; 5159 } 5160 } 5161 5162 /* Save next entry */ 5163 seg->fc_memsize = next->fc_memsize; 5164 seg->fc_numblks = next->fc_numblks; 5165 next->fc_memsize = 0; 5166 next->fc_numblks = 0; 5167 } 5168 5169 kmem_free(fct_memseg, fct_memseg_size); 5170 5171 /* Complete the initialization */ 5172 seg = port->fct_memseg; 5173 for (i = 0; i < port->fct_memseg_cnt; i++, seg++) { 5174 /* seg->fc_memsize = ; Already setup */ 5175 /* seg->fc_numblks = ; Already setup */ 5176 5177 (void) snprintf(seg->fc_label, sizeof (seg->fc_label), 5178 "FCT_DMEM_%d", seg->fc_memsize); 5179 5180 seg->fc_memtag = MEM_FCTSEG + i; 5181 seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG; 5182 seg->fc_memalign = 32; 5183 seg->fc_hi_water = 0xFFFF; 5184 seg->fc_lo_water = seg->fc_numblks; 5185 seg->fc_numblks = 0; 5186 seg->fc_step = 1; 5187 } 5188 5189 return; 5190 5191 } /* emlxs_fct_memseg_init() */ 5192 5193 5194 fct_status_t 5195 emlxs_fct_dmem_init(emlxs_port_t *port) 5196 { 5197 emlxs_hba_t *hba = HBA; 5198 emlxs_memseg_t *seg; 5199 int32_t i; 5200 5201 /* Initialize the fct memseg list */ 5202 emlxs_fct_memseg_init(hba); 5203 5204 if (!port->fct_memseg || !port->fct_memseg_cnt) { 5205 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5206 "fct_dmem_init: fct_memseg list is empty."); 5207 return (FCT_FAILURE); 5208 } 5209 5210 /* Create the DMA buffer pools */ 5211 seg = port->fct_memseg; 5212 for (i = 0; i < port->fct_memseg_cnt; i++, seg++) { 5213 5214 (void) emlxs_mem_pool_create(hba, seg); 5215 5216 if (seg->fc_numblks < seg->fc_lo_water) { 5217 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 5218 "%s: count=%d size=%d flags=%x lo=%d hi=%d", 5219 seg->fc_label, seg->fc_numblks, 5220 seg->fc_memsize, seg->fc_memflag, seg->fc_lo_water, 5221 seg->fc_hi_water); 5222 } 5223 } 5224 5225 return (FCT_SUCCESS); 5226 5227 } /* emlxs_fct_dmem_init */ 5228 5229 5230 void 5231 emlxs_fct_dmem_fini(emlxs_port_t *port) 5232 { 5233 emlxs_hba_t *hba = HBA; 5234 emlxs_memseg_t *seg; 5235 int32_t i; 5236 5237 if (!port->fct_memseg || !port->fct_memseg_cnt) { 5238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 5239 "fct_dmem_fini: fct_memseg list is empty."); 5240 return; 5241 } 5242 5243 /* Destroy the dmem buffer pools */ 5244 seg = port->fct_memseg; 5245 for (i = 0; i < port->fct_memseg_cnt; i++, seg++) { 5246 (void) emlxs_mem_pool_destroy(hba, seg); 5247 } 5248 5249 /* Clear the segment space */ 5250 kmem_free(port->fct_memseg, 5251 (port->fct_memseg_cnt * sizeof (emlxs_memseg_t))); 5252 5253 port->fct_memseg = 0; 5254 port->fct_memseg_cnt = 0; 5255 5256 return; 5257 5258 } /* emlxs_fct_dmem_fini */ 5259 5260 5261 /* COMSTAR ENTER POINT */ 5262 /*ARGSUSED*/ 5263 static stmf_data_buf_t * 5264 emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size, 5265 uint32_t *pminsize, uint32_t flags) 5266 { 5267 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 5268 emlxs_hba_t *hba = HBA; 5269 emlxs_memseg_t *seg; 5270 stmf_data_buf_t *db; 5271 MATCHMAP *mp; 5272 int i; 5273 uint32_t minsize = 0; 5274 5275 if (!port->fct_memseg || !port->fct_memseg_cnt) { 5276 goto failed; 5277 } 5278 5279 /* Check if our largest buffer is too small */ 5280 seg = &port->fct_memseg[port->fct_memseg_cnt-1]; 5281 if (size > seg->fc_memsize) { 5282 goto partial_alloc; 5283 } 5284 5285 /* Find smallest available buffer >= size */ 5286 seg = port->fct_memseg; 5287 for (i = 0; i < port->fct_memseg_cnt; i++, seg++) { 5288 if (seg->fc_memsize < size) { 5289 continue; 5290 } 5291 5292 mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg); 5293 5294 if (mp) { 5295 goto success; 5296 } 5297 } 5298 5299 seg = &port->fct_memseg[port->fct_memseg_cnt-1]; 5300 5301 partial_alloc: 5302 /* Find largest available buffer >= *pminsize */ 5303 for (i = port->fct_memseg_cnt-1; i >= 0; i--, seg--) { 5304 if (seg->fc_memsize < *pminsize) { 5305 minsize = seg->fc_memsize; 5306 goto failed; 5307 } 5308 5309 mp = (MATCHMAP*)emlxs_mem_pool_get(hba, seg); 5310 5311 if (mp) { 5312 goto success; 5313 } 5314 } 5315 5316 failed: 5317 *pminsize = minsize; 5318 TGTPORTSTAT.FctNoBuffer++; 5319 5320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5321 "fct_dbuf_alloc:Failed. size=%d minsize=%d", 5322 size, *pminsize); 5323 5324 return (NULL); 5325 5326 success: 5327 /* Setup the data buffer */ 5328 db = (stmf_data_buf_t *)mp->fct_private; 5329 db->db_data_size = min(size, mp->size); 5330 5331 #ifdef FCT_API_TRACE 5332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5333 "fct_dbuf_alloc:%p iotag=%d size=%d,%d", 5334 db, mp->tag, size, mp->size); 5335 #endif /* FCT_API_TRACE */ 5336 5337 return (db); 5338 5339 } /* emlxs_fct_dbuf_alloc() */ 5340 5341 5342 /* COMSTAR ENTER POINT */ 5343 /*ARGSUSED*/ 5344 static void 5345 emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *db) 5346 { 5347 emlxs_port_t *port = (emlxs_port_t *)fds->fds_fca_private; 5348 emlxs_hba_t *hba = HBA; 5349 MATCHMAP *mp = (MATCHMAP *)db->db_port_private; 5350 5351 if (!mp) { 5352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5353 "fct_dbuf_free:%p NULL mp found!", 5354 db); 5355 return; 5356 } 5357 5358 #ifdef FCT_API_TRACE 5359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5360 "fct_dbuf_free:%p iotag=%d", 5361 db, mp->tag); 5362 #endif /* FCT_API_TRACE */ 5363 5364 emlxs_mem_pool_put(hba, mp->segment, (void *)mp); 5365 5366 } /* emlxs_fct_dbuf_free() */ 5367 5368 5369 static int 5370 emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *db, 5371 uint_t sync_type) 5372 { 5373 emlxs_port_t *port = &PPORT; 5374 MATCHMAP *mp = (MATCHMAP *)db->db_port_private; 5375 5376 if (!mp) { 5377 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5378 "fct_dbuf_dma_sync:%p NULL mp found!", 5379 db); 5380 return (0); 5381 } 5382 5383 #ifdef FCT_API_TRACE 5384 { 5385 char buf[16]; 5386 5387 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 5388 "fct_dbuf_dma_sync:%p iotag=%d size=%d", 5389 db, mp->tag, db->db_data_size); 5390 5391 (void) snprintf(buf, sizeof (buf), "TAG%d:", mp->tag); 5392 emlxs_data_dump(port, buf, (uint32_t *)db->db_sglist[0].seg_addr, 5393 36, 0); 5394 } 5395 #endif /* FCT_API_TRACE */ 5396 5397 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, db->db_data_size, sync_type); 5398 5399 #ifdef FMA_SUPPORT 5400 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 5401 != DDI_FM_OK) { 5402 EMLXS_MSGF(EMLXS_CONTEXT, 5403 &emlxs_invalid_dma_handle_msg, 5404 "fct_dbuf_dma_sync:%p iotag=%d", 5405 db, mp->tag); 5406 return (1); 5407 } 5408 #endif /* FMA_SUPPORT */ 5409 5410 return (0); 5411 5412 } /* emlxs_fct_dbuf_dma_sync() */ 5413 5414 #endif /* SFCT_SUPPORT */ 5415