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