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