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