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