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