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 void emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type); 87 static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port, 88 fct_cmd_t *fct_cmd, fc_packet_t *pkt); 89 90 static void emlxs_fct_unsol_flush(emlxs_port_t *port); 91 static uint32_t emlxs_fct_process_unsol_flogi(emlxs_port_t *port, 92 CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); 93 static uint32_t emlxs_fct_process_unsol_plogi(emlxs_port_t *port, 94 CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); 95 static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port, 96 emlxs_buf_t *cmd_sbp); 97 static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port, 98 emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd); 99 static void emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type); 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; 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 emlxs_fct_dbuf_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV); 2592 } 2593 2594 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 2595 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_DATA_PENDING); 2596 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2597 2598 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, iocbq); 2599 2600 return (FCT_SUCCESS); 2601 2602 } /* emlxs_fct_send_fcp_data() */ 2603 2604 2605 /* cmd_sbp->fct_mtx must be held to enter */ 2606 /* cmd_sbp->fct_mtx must be released before exiting */ 2607 static fct_status_t 2608 emlxs_fct_send_fcp_status(fct_cmd_t *fct_cmd) 2609 { 2610 emlxs_port_t *port = 2611 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 2612 emlxs_hba_t *hba = HBA; 2613 emlxs_buf_t *cmd_sbp; 2614 scsi_task_t *fct_task; 2615 fc_packet_t *pkt; 2616 uint32_t did; 2617 emlxs_fcp_rsp *fcp_rsp; 2618 uint32_t size; 2619 emlxs_node_t *ndlp; 2620 fct_status_t rval; 2621 2622 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 2623 ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 2624 did = fct_cmd->cmd_rportid; 2625 2626 /* Initialize cmd_sbp */ 2627 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2628 2629 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_FCP_STATUS); 2630 2631 cmd_sbp->node = ndlp; 2632 2633 size = 24; 2634 if (fct_task->task_sense_length) { 2635 size += fct_task->task_sense_length; 2636 } 2637 #ifdef FCT_API_TRACE 2638 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2639 "emlxs_fct_send_fcp_status %p: stat=%d resid=%d size=%d rx=%x", 2640 fct_cmd, fct_task->task_scsi_status, 2641 fct_task->task_resid, size, fct_cmd->cmd_rxid); 2642 #endif /* FCT_API_TRACE */ 2643 2644 if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) { 2645 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2646 "emlxs_fct_send_fcp_status: Unable to allocate packet."); 2647 2648 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2649 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2650 2651 return (FCT_BUSY); 2652 } 2653 2654 cmd_sbp->fct_type = EMLXS_FCT_FCP_STATUS; 2655 2656 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 2657 cmd_sbp->fct_pkt = pkt; 2658 2659 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2660 pkt->pkt_timeout = 2661 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 2662 pkt->pkt_comp = emlxs_fct_pkt_comp; 2663 2664 /* Build the fc header */ 2665 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 2666 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 2667 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 2668 pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP; 2669 pkt->pkt_cmd_fhdr.f_ctl = 2670 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2671 pkt->pkt_cmd_fhdr.seq_id = 0; 2672 pkt->pkt_cmd_fhdr.df_ctl = 0; 2673 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2674 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 2675 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 2676 pkt->pkt_cmd_fhdr.ro = 0; 2677 2678 /* Build the status payload */ 2679 fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd; 2680 2681 if (fct_task->task_resid) { 2682 if (fct_task->task_status_ctrl & TASK_SCTRL_OVER) { 2683 TGTPORTSTAT.FctScsiResidOver++; 2684 fcp_rsp->rspStatus2 |= RESID_OVER; 2685 fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid); 2686 2687 } else if (fct_task->task_status_ctrl & TASK_SCTRL_UNDER) { 2688 TGTPORTSTAT.FctScsiResidUnder++; 2689 fcp_rsp->rspStatus2 |= RESID_UNDER; 2690 fcp_rsp->rspResId = LE_SWAP32(fct_task->task_resid); 2691 2692 } 2693 } 2694 2695 if (fct_task->task_scsi_status) { 2696 if (fct_task->task_scsi_status == SCSI_STAT_QUE_FULL) { 2697 TGTPORTSTAT.FctScsiQfullErr++; 2698 } else { 2699 TGTPORTSTAT.FctScsiStatusErr++; 2700 } 2701 2702 /* Make sure residual reported on non-SCSI_GOOD READ status */ 2703 if ((fct_task->task_flags & TF_READ_DATA) && 2704 (fcp_rsp->rspResId == 0)) { 2705 fcp_rsp->rspStatus2 |= RESID_UNDER; 2706 fcp_rsp->rspResId = 2707 fct_task->task_expected_xfer_length; 2708 } 2709 } 2710 2711 2712 if (fct_task->task_sense_length) { 2713 TGTPORTSTAT.FctScsiSenseErr++; 2714 fcp_rsp->rspStatus2 |= SNS_LEN_VALID; 2715 fcp_rsp->rspSnsLen = LE_SWAP32(fct_task->task_sense_length); 2716 2717 bcopy((uint8_t *)fct_task->task_sense_data, 2718 (uint8_t *)&fcp_rsp->rspInfo0, 2719 fct_task->task_sense_length); 2720 } 2721 2722 fcp_rsp->rspStatus3 = fct_task->task_scsi_status; 2723 fcp_rsp->rspRspLen = 0; 2724 2725 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 2726 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_STATUS_PENDING); 2727 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2728 2729 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 2730 2731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2732 "emlxs_fct_send_fcp_status: Unable to send packet."); 2733 2734 /* Reacquire ownership of the fct_cmd */ 2735 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 2736 if (rval) { 2737 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2738 "emlxs_fct_send_fcp_status: " 2739 "Unable to acquire fct_cmd."); 2740 return (rval); 2741 } 2742 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2743 2744 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2745 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2746 2747 return (FCT_BUSY); 2748 } 2749 2750 return (FCT_SUCCESS); 2751 2752 } /* emlxs_fct_send_fcp_status() */ 2753 2754 2755 static fct_status_t 2756 emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp, 2757 uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd) 2758 { 2759 emlxs_hba_t *hba = HBA; 2760 emlxs_buf_t *sbp; 2761 fc_packet_t *pkt; 2762 emlxs_fcp_rsp *fcp_rsp; 2763 uint32_t size; 2764 CHANNEL *cp = &hba->chan[hba->CHANNEL_FCT]; 2765 uint8_t lun[8]; 2766 2767 bcopy((void *)&fcp_cmd->fcpLunMsl, lun, 8); 2768 size = 24; 2769 2770 if (!(pkt = emlxs_pkt_alloc(port, size, 0, 0, KM_NOSLEEP))) { 2771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2772 "emlxs_fct_send_qfull_reply: Unable to allocate packet."); 2773 return (FCT_FAILURE); 2774 } 2775 2776 2777 sbp = PKT2PRIV(pkt); 2778 sbp->node = ndlp; 2779 sbp->channel = cp; 2780 sbp->did = ndlp->nlp_DID; 2781 sbp->lun = (lun[0] << 8) | lun[1]; 2782 sbp->class = class; 2783 2784 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 2785 pkt->pkt_timeout = 2786 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 2787 2788 /* Build the fc header */ 2789 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID); 2790 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 2791 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 2792 pkt->pkt_cmd_fhdr.type = FC_TYPE_SCSI_FCP; 2793 pkt->pkt_cmd_fhdr.f_ctl = 2794 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 2795 pkt->pkt_cmd_fhdr.seq_id = 0; 2796 pkt->pkt_cmd_fhdr.df_ctl = 0; 2797 pkt->pkt_cmd_fhdr.seq_cnt = 0; 2798 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 2799 pkt->pkt_cmd_fhdr.rx_id = xid; 2800 pkt->pkt_cmd_fhdr.ro = 0; 2801 2802 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2803 "emlxs_fct_send_qfull_reply: Sending QFULL: x%x lun x%x: %d %d", 2804 xid, sbp->lun, TGTPORTSTAT.FctOutstandingIO, 2805 port->fct_port->port_max_xchges); 2806 2807 /* Build the status payload */ 2808 fcp_rsp = (emlxs_fcp_rsp *)pkt->pkt_cmd; 2809 2810 TGTPORTSTAT.FctScsiQfullErr++; 2811 fcp_rsp->rspStatus3 = SCSI_STAT_QUE_FULL; 2812 fcp_rsp->rspStatus2 |= RESID_UNDER; 2813 fcp_rsp->rspResId = LE_SWAP32(fcp_cmd->fcpDl); 2814 2815 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 2816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2817 "emlxs_fct_send_qfull_reply: Unable to send packet."); 2818 emlxs_pkt_free(pkt); 2819 return (FCT_FAILURE); 2820 } 2821 2822 return (FCT_SUCCESS); 2823 2824 } /* emlxs_fct_send_qfull_reply() */ 2825 2826 2827 /* ARGSUSED */ 2828 extern int 2829 emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2830 { 2831 emlxs_port_t *port = &PPORT; 2832 IOCB *iocb; 2833 emlxs_buf_t *sbp; 2834 emlxs_buf_t *cmd_sbp; 2835 uint32_t status; 2836 fct_cmd_t *fct_cmd; 2837 stmf_data_buf_t *dbuf; 2838 scsi_task_t *fct_task; 2839 fc_packet_t *pkt; 2840 uint32_t fct_flags; 2841 stmf_data_buf_t *fct_buf; 2842 fct_status_t rval; 2843 2844 iocb = &iocbq->iocb; 2845 sbp = (emlxs_buf_t *)iocbq->sbp; 2846 2847 TGTPORTSTAT.FctEvent++; 2848 2849 if (!sbp) { 2850 /* completion with missing xmit command */ 2851 TGTPORTSTAT.FctStray++; 2852 2853 /* emlxs_stray_fcp_completion_msg */ 2854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2855 "FCP event cmd=%x status=%x error=%x iotag=%x", 2856 iocb->ULPCOMMAND, iocb->ULPSTATUS, 2857 iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG); 2858 2859 return (1); 2860 } 2861 2862 TGTPORTSTAT.FctCompleted++; 2863 2864 port = sbp->iocbq.port; 2865 fct_cmd = sbp->fct_cmd; 2866 status = iocb->ULPSTATUS; 2867 2868 #ifdef FCT_API_TRACE 2869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2870 "emlxs_fct_handle_fcp_event: %p: cmd=%x status=%x, %x", 2871 fct_cmd, iocb->ULPCOMMAND, status, iocb->ULPCT); 2872 #endif /* FCT_API_TRACE */ 2873 2874 if (fct_cmd == NULL) { 2875 /* For driver generated QFULL response */ 2876 if (((iocb->ULPCOMMAND == CMD_FCP_TRSP_CX) || 2877 (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX)) && sbp->pkt) { 2878 emlxs_pkt_free(sbp->pkt); 2879 } 2880 return (0); 2881 } 2882 2883 rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_REQ_COMPLETE); 2884 if (rval) { 2885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 2886 "emlxs_fct_handle_fcp_event: " 2887 "Unable to reacquire fct_cmd. type=%x", 2888 fct_cmd->cmd_type); 2889 2890 return (1); 2891 } 2892 /* mutex_enter(&cmd_sbp->fct_mtx); */ 2893 2894 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 2895 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 2896 2897 pkt = cmd_sbp->fct_pkt; 2898 cmd_sbp->fct_pkt = NULL; 2899 2900 dbuf = sbp->fct_buf; 2901 2902 fct_cmd->cmd_comp_status = FCT_SUCCESS; 2903 2904 if (status) { 2905 /* 2906 * The error indicates this IO should be terminated 2907 * immediately. 2908 */ 2909 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 2910 fct_cmd->cmd_comp_status = FCT_FAILURE; 2911 2912 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 2913 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2914 2915 #ifdef FCT_API_TRACE 2916 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2917 "fct_queue_cmd_for_termination:1 %p: x%x", 2918 fct_cmd, fct_cmd->cmd_comp_status); 2919 #endif /* FCT_API_TRACE */ 2920 2921 MODSYM(fct_queue_cmd_for_termination) (fct_cmd, 2922 FCT_ABTS_RECEIVED); 2923 2924 goto done; 2925 } 2926 2927 switch (iocb->ULPCOMMAND) { 2928 2929 /* 2930 * FCP Data completion 2931 */ 2932 case CMD_FCP_TSEND_CX: 2933 case CMD_FCP_TSEND64_CX: 2934 case CMD_FCP_TRECEIVE_CX: 2935 case CMD_FCP_TRECEIVE64_CX: 2936 2937 if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) { 2938 emlxs_fct_dbuf_dma_sync(dbuf, 2939 DDI_DMA_SYNC_FORCPU); 2940 } 2941 2942 if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) && 2943 (iocb->ULPCT != 1)) { 2944 2945 dbuf->db_flags |= DB_STATUS_GOOD_SENT; 2946 2947 fct_task = 2948 (scsi_task_t *)fct_cmd->cmd_specific; 2949 fct_task->task_scsi_status = 0; 2950 2951 (void) emlxs_fct_send_fcp_status(fct_cmd); 2952 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2953 2954 break; 2955 2956 } else if ((cmd_sbp->fct_flags & 2957 EMLXS_FCT_SEND_STATUS) && 2958 (iocb->ULPCT == 1)) { 2959 /* Auto-resp has been sent out by firmware */ 2960 /* We can assume this is really a FC_TRSP_CX */ 2961 2962 dbuf->db_flags |= DB_STATUS_GOOD_SENT; 2963 fct_task = 2964 (scsi_task_t *)fct_cmd->cmd_specific; 2965 fct_task->task_scsi_status = 0; 2966 2967 cmd_sbp->fct_flags |= EMLXS_FCT_SEND_STATUS; 2968 2969 goto auto_resp; 2970 } 2971 2972 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 2973 2974 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 2975 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2976 2977 #ifdef FCT_API_TRACE 2978 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 2979 "fct_scsi_data_xfer_done:1 %p %p", fct_cmd, dbuf); 2980 #endif /* FCT_API_TRACE */ 2981 2982 MODSYM(fct_scsi_data_xfer_done) (fct_cmd, dbuf, 0); 2983 2984 break; 2985 2986 /* FCP Status completion */ 2987 case CMD_FCP_TRSP_CX: 2988 case CMD_FCP_TRSP64_CX: 2989 2990 auto_resp: 2991 /* Copy these before calling emlxs_fct_cmd_done */ 2992 fct_flags = cmd_sbp->fct_flags; 2993 fct_buf = cmd_sbp->fct_buf; 2994 2995 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 2996 /* mutex_exit(&cmd_sbp->fct_mtx); */ 2997 2998 TGTPORTSTAT.FctOutstandingIO--; 2999 3000 if (fct_flags & EMLXS_FCT_SEND_STATUS) { 3001 #ifdef FCT_API_TRACE 3002 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3003 "fct_scsi_data_xfer_done:2 %p %p", 3004 fct_cmd, fct_buf); 3005 #endif /* FCT_API_TRACE */ 3006 3007 MODSYM(fct_scsi_data_xfer_done) (fct_cmd, 3008 fct_buf, FCT_IOF_FCA_DONE); 3009 } else { 3010 #ifdef FCT_API_TRACE 3011 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3012 "fct_send_response_done:1 %p: x%x", 3013 fct_cmd, fct_cmd->cmd_comp_status); 3014 #endif /* FCT_API_TRACE */ 3015 3016 MODSYM(fct_send_response_done) (fct_cmd, 3017 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3018 } 3019 break; 3020 3021 default: 3022 emlxs_fct_cmd_release(port, fct_cmd, 0); 3023 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3024 3025 TGTPORTSTAT.FctStray++; 3026 TGTPORTSTAT.FctCompleted--; 3027 3028 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3029 "Invalid iocb: cmd=0x%x", iocb->ULPCOMMAND); 3030 3031 if (pkt) { 3032 emlxs_pkt_complete(sbp, status, 3033 iocb->un.grsp.perr.statLocalError, 1); 3034 } 3035 3036 } /* switch(iocb->ULPCOMMAND) */ 3037 3038 3039 done: 3040 if (pkt) { 3041 emlxs_pkt_free(pkt); 3042 } 3043 3044 if (status == IOSTAT_SUCCESS) { 3045 TGTPORTSTAT.FctCmplGood++; 3046 } else { 3047 TGTPORTSTAT.FctCmplError++; 3048 } 3049 3050 return (0); 3051 3052 } /* emlxs_fct_handle_fcp_event() */ 3053 3054 3055 /* ARGSUSED */ 3056 extern int 3057 emlxs_fct_handle_abort(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 3058 { 3059 emlxs_port_t *port = &PPORT; 3060 IOCB *iocb; 3061 emlxs_buf_t *sbp; 3062 fc_packet_t *pkt; 3063 3064 iocb = &iocbq->iocb; 3065 sbp = (emlxs_buf_t *)iocbq->sbp; 3066 3067 TGTPORTSTAT.FctEvent++; 3068 3069 if (!sbp) { 3070 /* completion with missing xmit command */ 3071 TGTPORTSTAT.FctStray++; 3072 3073 /* emlxs_stray_fcp_completion_msg */ 3074 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3075 "ABORT event cmd=%x status=%x error=%x iotag=%x", 3076 iocb->ULPCOMMAND, iocb->ULPSTATUS, 3077 iocb->un.grsp.perr.statLocalError, iocb->ULPIOTAG); 3078 3079 return (1); 3080 } 3081 3082 pkt = PRIV2PKT(sbp); 3083 3084 #ifdef FCT_API_TRACE 3085 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3086 "emlxs_fct_handle_abort: %p: xri=%x status=%x", iocb->ULPCONTEXT, 3087 iocb->ULPCOMMAND, iocb->ULPSTATUS); 3088 #endif /* FCT_API_TRACE */ 3089 3090 3091 if (pkt) { 3092 emlxs_pkt_free(pkt); 3093 } 3094 return (0); 3095 3096 } /* emlxs_fct_handle_abort() */ 3097 3098 3099 extern int 3100 emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3101 MATCHMAP *mp, uint32_t size) 3102 { 3103 emlxs_hba_t *hba = HBA; 3104 IOCB *iocb; 3105 uint32_t cmd_code; 3106 fct_cmd_t *fct_cmd; 3107 fct_els_t *els; 3108 uint32_t sid; 3109 uint32_t padding; 3110 uint8_t *bp; 3111 emlxs_buf_t *cmd_sbp; 3112 uint32_t rval; 3113 3114 HBASTATS.ElsCmdReceived++; 3115 3116 bp = mp->virt; 3117 cmd_code = (*(uint32_t *)bp) & ELS_CMD_MASK; 3118 iocb = &iocbq->iocb; 3119 sid = iocb->un.elsreq.remoteID; 3120 3121 if (!port->fct_port) { 3122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3123 "%s: sid=%x. Target unbound. Rejecting...", 3124 emlxs_elscmd_xlate(cmd_code), sid); 3125 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, 3126 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 3127 3128 goto done; 3129 } 3130 3131 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 3132 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3133 "%s: sid=%x. Target offline. Rejecting...", 3134 emlxs_elscmd_xlate(cmd_code), sid); 3135 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, 3136 LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); 3137 3138 goto done; 3139 } 3140 3141 /* Process the request */ 3142 switch (cmd_code) { 3143 case ELS_CMD_FLOGI: 3144 rval = emlxs_fct_process_unsol_flogi(port, cp, iocbq, mp, size); 3145 3146 if (!rval) { 3147 ELS_PKT *els_pkt = (ELS_PKT *)bp; 3148 fct_flogi_xchg_t fx; 3149 3150 bzero((uint8_t *)&fx, sizeof (fct_flogi_xchg_t)); 3151 3152 /* Save the FLOGI exchange information */ 3153 fx.rsvd2 = iocb->ULPCONTEXT; 3154 bcopy((caddr_t)&els_pkt->un.logi.nodeName, 3155 (caddr_t)fx.fx_nwwn, 8); 3156 bcopy((caddr_t)&els_pkt->un.logi.portName, 3157 (caddr_t)fx.fx_pwwn, 8); 3158 fx.fx_sid = sid; 3159 fx.fx_did = iocb->un.elsreq.myID; 3160 fx.fx_fport = els_pkt->un.logi.cmn.fPort; 3161 fx.fx_op = ELS_OP_FLOGI; 3162 3163 emlxs_fct_handle_unsol_flogi(port, &fx, 1); 3164 } 3165 3166 goto done; 3167 3168 case ELS_CMD_PLOGI: 3169 rval = 3170 emlxs_fct_process_unsol_plogi(port, cp, iocbq, mp, size); 3171 break; 3172 3173 default: 3174 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3175 "%s: sid=0x%x", emlxs_elscmd_xlate(cmd_code), sid); 3176 rval = 0; 3177 break; 3178 } 3179 3180 if (rval) { 3181 goto done; 3182 } 3183 3184 padding = (8 - (size & 7)) & 7; 3185 3186 fct_cmd = (fct_cmd_t *)MODSYM(fct_alloc) (FCT_STRUCT_CMD_RCVD_ELS, 3187 (size + padding + GET_STRUCT_SIZE(emlxs_buf_t)), 3188 AF_FORCE_NOSLEEP); 3189 3190 #ifdef FCT_API_TRACE 3191 { 3192 uint32_t *ptr = (uint32_t *)bp; 3193 3194 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3195 "fct_alloc %p: ELS rcvd: rxid=%x payload: x%x x%x", 3196 fct_cmd, iocb->ULPCONTEXT, *ptr, *(ptr + 1)); 3197 } 3198 #endif /* FCT_API_TRACE */ 3199 3200 if (fct_cmd == NULL) { 3201 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3202 "%s: sid=%x. Out of memory. Rejecting...", 3203 emlxs_elscmd_xlate(cmd_code), sid); 3204 3205 (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, 3206 LSRJT_LOGICAL_BSY, LSEXP_OUT_OF_RESOURCE); 3207 goto done; 3208 } 3209 3210 /* Initialize fct_cmd */ 3211 fct_cmd->cmd_oxid = (cmd_code >> ELS_CMD_SHIFT) & 0xff; 3212 fct_cmd->cmd_rxid = iocb->ULPCONTEXT; 3213 fct_cmd->cmd_rportid = sid; 3214 fct_cmd->cmd_lportid = port->did; 3215 fct_cmd->cmd_rp_handle = iocb->ULPIOTAG; /* RPI */ 3216 fct_cmd->cmd_port = port->fct_port; 3217 3218 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_ELS_CMD_RECEIVED); 3219 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3220 3221 /* Initialize cmd_sbp */ 3222 cmd_sbp->channel = cp; 3223 cmd_sbp->class = iocb->ULPCLASS; 3224 cmd_sbp->fct_type = EMLXS_FCT_ELS_CMD; 3225 cmd_sbp->fct_flags |= EMLXS_FCT_PLOGI_RECEIVED; 3226 3227 bcopy((uint8_t *)iocb, (uint8_t *)&cmd_sbp->iocbq, 3228 sizeof (emlxs_iocb_t)); 3229 3230 els = (fct_els_t *)fct_cmd->cmd_specific; 3231 els->els_req_size = size; 3232 els->els_req_payload = 3233 GET_BYTE_OFFSET(fct_cmd->cmd_fca_private, 3234 GET_STRUCT_SIZE(emlxs_buf_t)); 3235 bcopy(bp, els->els_req_payload, size); 3236 3237 3238 /* Check if Offline */ 3239 if (!(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 3240 3241 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 3242 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3243 3244 #ifdef FCT_API_TRACE 3245 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3246 "fct_post_rcvd_cmd:4 %p: portid x%x", fct_cmd, 3247 fct_cmd->cmd_lportid); 3248 #endif /* FCT_API_TRACE */ 3249 3250 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 3251 3252 goto done; 3253 } 3254 3255 /* Online */ 3256 /* Check if Link up is acked */ 3257 if (port->fct_flags & FCT_STATE_LINK_UP_ACKED) { 3258 3259 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 3260 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3261 3262 #ifdef FCT_API_TRACE 3263 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3264 "fct_post_rcvd_cmd:1 %p: portid x%x", fct_cmd, 3265 fct_cmd->cmd_lportid); 3266 #endif /* FCT_API_TRACE */ 3267 3268 MODSYM(fct_post_rcvd_cmd) (fct_cmd, 0); 3269 3270 goto done; 3271 3272 } 3273 3274 /* Defer processing of fct_cmd till later (after link up ack). */ 3275 3276 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_CMD_WAITQ); 3277 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3278 3279 /* Add cmd_sbp to queue tail */ 3280 mutex_enter(&EMLXS_PORT_LOCK); 3281 3282 if (port->fct_wait_tail) { 3283 port->fct_wait_tail->next = cmd_sbp; 3284 } 3285 port->fct_wait_tail = cmd_sbp; 3286 3287 if (!port->fct_wait_head) { 3288 port->fct_wait_head = cmd_sbp; 3289 } 3290 3291 mutex_exit(&EMLXS_PORT_LOCK); 3292 3293 done: 3294 3295 return (0); 3296 3297 } /* emlxs_fct_handle_unsol_els() */ 3298 3299 3300 /* ARGSUSED */ 3301 static uint32_t 3302 emlxs_fct_process_unsol_flogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3303 MATCHMAP *mp, uint32_t size) 3304 { 3305 IOCB *iocb; 3306 char buffer[64]; 3307 3308 buffer[0] = 0; 3309 3310 iocb = &iocbq->iocb; 3311 3312 /* Perform processing of FLOGI payload */ 3313 if (emlxs_process_unsol_flogi(port, iocbq, mp, size, buffer)) { 3314 return (1); 3315 } 3316 3317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3318 "FLOGI: sid=0x%x xid=%x %s", 3319 iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer); 3320 3321 return (0); 3322 3323 } /* emlxs_fct_process_unsol_flogi() */ 3324 3325 3326 /* ARGSUSED */ 3327 static uint32_t 3328 emlxs_fct_process_unsol_plogi(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, 3329 MATCHMAP *mp, uint32_t size) 3330 { 3331 IOCB *iocb; 3332 char buffer[64]; 3333 3334 buffer[0] = 0; 3335 3336 iocb = &iocbq->iocb; 3337 3338 /* Perform processing of PLOGI payload */ 3339 if (emlxs_process_unsol_plogi(port, iocbq, mp, size, buffer)) { 3340 return (1); 3341 } 3342 3343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3344 "PLOGI: sid=0x%x xid=%x %s", 3345 iocb->un.elsreq.remoteID, iocb->ULPIOTAG, buffer); 3346 3347 return (0); 3348 3349 } /* emlxs_fct_process_unsol_plogi() */ 3350 3351 3352 /* ARGSUSED */ 3353 static emlxs_buf_t * 3354 emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3355 fc_packet_t *pkt) 3356 { 3357 emlxs_buf_t *cmd_sbp; 3358 emlxs_buf_t *sbp; 3359 3360 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3361 3362 sbp = PKT2PRIV(pkt); 3363 sbp->fct_cmd = cmd_sbp->fct_cmd; 3364 sbp->node = cmd_sbp->node; 3365 sbp->channel = cmd_sbp->channel; 3366 sbp->did = cmd_sbp->did; 3367 sbp->lun = cmd_sbp->lun; 3368 sbp->class = cmd_sbp->class; 3369 sbp->fct_type = cmd_sbp->fct_type; 3370 sbp->fct_state = cmd_sbp->fct_state; 3371 3372 return (sbp); 3373 3374 } /* emlxs_fct_pkt_init() */ 3375 3376 3377 /* Mutex will be acquired */ 3378 static emlxs_buf_t * 3379 emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t fct_state) 3380 { 3381 emlxs_hba_t *hba = HBA; 3382 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3383 3384 bzero((void *)cmd_sbp, sizeof (emlxs_buf_t)); 3385 mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER, 3386 (void *)hba->intr_arg); 3387 mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg); 3388 3389 mutex_enter(&cmd_sbp->fct_mtx); 3390 cmd_sbp->pkt_flags = PACKET_VALID; 3391 cmd_sbp->port = port; 3392 cmd_sbp->fct_cmd = fct_cmd; 3393 cmd_sbp->node = (fct_cmd->cmd_rp) ? 3394 *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private : NULL; 3395 cmd_sbp->iocbq.sbp = cmd_sbp; 3396 cmd_sbp->iocbq.port = port; 3397 cmd_sbp->did = fct_cmd->cmd_rportid; 3398 3399 /* Flags fct_cmd as inuse */ 3400 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3401 fct_cmd->cmd_oxid = 0xffff; 3402 fct_cmd->cmd_rxid = 0xffff; 3403 } 3404 3405 if (fct_state) { 3406 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3407 } 3408 3409 return (cmd_sbp); 3410 3411 } /* emlxs_fct_cmd_init() */ 3412 3413 3414 /* Called after receiving fct_cmd from COMSTAR */ 3415 static fct_status_t 3416 emlxs_fct_cmd_accept(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) 3417 { 3418 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3419 3420 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3421 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3422 "emlxs_fct_cmd_accept: " 3423 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3424 fct_cmd, fct_state); 3425 3426 return (FCT_NOT_FOUND); 3427 } 3428 3429 mutex_enter(&cmd_sbp->fct_mtx); 3430 3431 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3432 mutex_exit(&cmd_sbp->fct_mtx); 3433 3434 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3435 "emlxs_fct_cmd_accept:2 " 3436 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3437 fct_cmd, fct_state); 3438 3439 return (FCT_NOT_FOUND); 3440 } 3441 3442 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 3443 3444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3445 "emlxs_fct_cmd_accept: " 3446 "Aborted fct_cmd found! fct_cmd=%p state=%x", 3447 fct_cmd, fct_state); 3448 3449 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE); 3450 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3451 3452 MODSYM(fct_cmd_fca_aborted) (fct_cmd, 3453 FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 3454 3455 return (FCT_NOT_FOUND); 3456 } 3457 3458 mutex_enter(&cmd_sbp->mtx); 3459 if (!(cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3460 mutex_exit(&cmd_sbp->mtx); 3461 mutex_exit(&cmd_sbp->fct_mtx); 3462 3463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3464 "emlxs_fct_cmd_accept: " 3465 "Busy fct_cmd found! fct_cmd=%p state=%x", 3466 fct_cmd, fct_state); 3467 3468 return (FCT_BUSY); 3469 } 3470 cmd_sbp->pkt_flags &= ~PACKET_ULP_OWNED; 3471 mutex_exit(&cmd_sbp->mtx); 3472 3473 if (fct_state) { 3474 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3475 } 3476 3477 return (FCT_SUCCESS); 3478 3479 } /* emlxs_fct_cmd_accept() */ 3480 3481 3482 /* Called after receiving fct_cmd from driver */ 3483 static fct_status_t 3484 emlxs_fct_cmd_acquire(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3485 uint16_t fct_state) 3486 { 3487 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3488 3489 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3490 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3491 "emlxs_fct_cmd_acquire: " 3492 "Bad fct_cmd found! fct_cmd=%p state=%x", 3493 fct_cmd, fct_state); 3494 3495 return (FCT_NOT_FOUND); 3496 } 3497 3498 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3499 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3500 "emlxs_fct_cmd_acquire: " 3501 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3502 fct_cmd, fct_state); 3503 3504 return (FCT_NOT_FOUND); 3505 } 3506 3507 if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3509 "emlxs_fct_cmd_acquire: " 3510 "Returned fct_cmd found! fct_cmd=%p state=%x", 3511 fct_cmd, fct_state); 3512 3513 return (FCT_NOT_FOUND); 3514 } 3515 3516 mutex_enter(&cmd_sbp->fct_mtx); 3517 3518 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 3519 mutex_exit(&cmd_sbp->fct_mtx); 3520 3521 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3522 "emlxs_fct_cmd_acquire:2 " 3523 "Bad fct_cmd found! fct_cmd=%p state=%x", 3524 fct_cmd, fct_state); 3525 3526 return (FCT_NOT_FOUND); 3527 } 3528 3529 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 3530 mutex_exit(&cmd_sbp->fct_mtx); 3531 3532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3533 "emlxs_fct_cmd_acquire:2 " 3534 "Invalid fct_cmd found! fct_cmd=%p state=%x", 3535 fct_cmd, fct_state); 3536 3537 return (FCT_NOT_FOUND); 3538 } 3539 3540 if ((cmd_sbp->pkt_flags & PACKET_ULP_OWNED)) { 3541 mutex_exit(&cmd_sbp->fct_mtx); 3542 3543 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3544 "emlxs_fct_cmd_acquire:2 " 3545 "Returned fct_cmd found! fct_cmd=%p state=%x", 3546 fct_cmd, fct_state); 3547 3548 return (FCT_NOT_FOUND); 3549 } 3550 3551 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 3552 3553 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3554 "emlxs_fct_cmd_acquire: " 3555 "Aborting cmd. fct_cmd=%p state=%x", 3556 fct_cmd, fct_state); 3557 3558 if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) { 3559 TGTPORTSTAT.FctOutstandingIO--; 3560 } 3561 3562 fct_cmd->cmd_comp_status = FCT_FAILURE; 3563 3564 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_ABORT_DONE); 3565 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3566 3567 MODSYM(fct_cmd_fca_aborted) (fct_cmd, 3568 FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 3569 3570 return (FCT_NOT_FOUND); 3571 } 3572 3573 if (fct_state) { 3574 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3575 } 3576 3577 return (FCT_SUCCESS); 3578 3579 } /* emlxs_fct_cmd_acquire() */ 3580 3581 3582 /* cmd_sbp->fct_mtx must be held to enter */ 3583 /* cmd_sbp->fct_mtx must be released before exiting */ 3584 /* Called before transitionally sending fct_cmd to driver */ 3585 /*ARGSUSED*/ 3586 static void 3587 emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3588 uint16_t fct_state) 3589 { 3590 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3591 3592 if (fct_state) { 3593 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3594 } 3595 3596 mutex_exit(&cmd_sbp->fct_mtx); 3597 3598 return; 3599 3600 } /* emlxs_fct_cmd_release() */ 3601 3602 3603 /* cmd_sbp->fct_mtx must be held to enter */ 3604 /* cmd_sbp->fct_mtx must be released before exiting */ 3605 /* Called before posting fct_cmd back to COMSTAR */ 3606 /*ARGSUSED*/ 3607 static void 3608 emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd, 3609 uint16_t fct_state) 3610 { 3611 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3612 fc_packet_t *pkt; 3613 3614 pkt = cmd_sbp->fct_pkt; 3615 cmd_sbp->fct_pkt = NULL; 3616 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3617 3618 mutex_enter(&cmd_sbp->mtx); 3619 cmd_sbp->pkt_flags |= PACKET_ULP_OWNED; 3620 mutex_exit(&cmd_sbp->mtx); 3621 3622 if (fct_state) { 3623 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3624 } 3625 3626 mutex_exit(&cmd_sbp->fct_mtx); 3627 3628 if (pkt) { 3629 emlxs_pkt_free(pkt); 3630 } 3631 3632 return; 3633 3634 } /* emlxs_fct_cmd_post() */ 3635 3636 3637 /* cmd_sbp->fct_mtx must be held to enter */ 3638 /* Called before completing fct_cmd back to COMSTAR */ 3639 static void 3640 emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) 3641 { 3642 emlxs_hba_t *hba = HBA; 3643 emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3644 fc_packet_t *pkt; 3645 3646 /* Flags fct_cmd is no longer used */ 3647 fct_cmd->cmd_oxid = 0; 3648 fct_cmd->cmd_rxid = 0; 3649 3650 if (cmd_sbp->iotag != 0) { 3651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3652 "Pkt still registered! channel=%d iotag=%d sbp=%p", 3653 cmd_sbp->channel, cmd_sbp->iotag, cmd_sbp); 3654 3655 if (cmd_sbp->channel) { 3656 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3657 hba->fc_table[cmd_sbp->iotag] = NULL; 3658 emlxs_sli4_free_xri(hba, cmd_sbp, cmd_sbp->xp); 3659 } else { 3660 (void) emlxs_unregister_pkt(cmd_sbp->channel, 3661 cmd_sbp->iotag, 0); 3662 } 3663 3664 } 3665 } 3666 3667 pkt = cmd_sbp->fct_pkt; 3668 cmd_sbp->fct_pkt = NULL; 3669 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3670 3671 if (fct_state) { 3672 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, fct_state); 3673 } 3674 3675 mutex_enter(&cmd_sbp->mtx); 3676 cmd_sbp->pkt_flags |= PACKET_ULP_OWNED; 3677 cmd_sbp->pkt_flags &= ~PACKET_VALID; 3678 mutex_exit(&cmd_sbp->mtx); 3679 mutex_exit(&cmd_sbp->fct_mtx); 3680 3681 3682 mutex_destroy(&cmd_sbp->fct_mtx); 3683 mutex_destroy(&cmd_sbp->mtx); 3684 3685 if (pkt) { 3686 emlxs_pkt_free(pkt); 3687 } 3688 3689 return; 3690 3691 } /* emlxs_fct_cmd_done() */ 3692 3693 3694 static void 3695 emlxs_fct_pkt_comp(fc_packet_t *pkt) 3696 { 3697 emlxs_port_t *port; 3698 #ifdef FMA_SUPPORT 3699 emlxs_hba_t *hba; 3700 #endif /* FMA_SUPPORT */ 3701 emlxs_buf_t *sbp; 3702 emlxs_buf_t *cmd_sbp; 3703 fct_cmd_t *fct_cmd; 3704 fct_els_t *fct_els; 3705 fct_sol_ct_t *fct_ct; 3706 fct_status_t rval; 3707 3708 sbp = PKT2PRIV(pkt); 3709 port = sbp->port; 3710 #ifdef FMA_SUPPORT 3711 hba = HBA; 3712 #endif /* FMA_SUPPORT */ 3713 fct_cmd = sbp->fct_cmd; 3714 3715 rval = emlxs_fct_cmd_acquire(port, fct_cmd, EMLXS_FCT_PKT_COMPLETE); 3716 if (rval) { 3717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3718 "emlxs_fct_pkt_comp: " 3719 "Unable to reacquire fct_cmd."); 3720 return; 3721 } 3722 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3723 3724 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 3725 cmd_sbp->fct_flags &= ~EMLXS_FCT_IO_INP; 3726 cmd_sbp->fct_pkt = NULL; 3727 3728 switch (fct_cmd->cmd_type) { 3729 case FCT_CMD_FCP_XCHG: 3730 if ((pkt->pkt_reason == FC_REASON_ABORTED) || 3731 (pkt->pkt_reason == FC_REASON_XCHG_DROPPED) || 3732 (pkt->pkt_reason == FC_REASON_OFFLINE)) { 3733 /* 3734 * The error indicates this IO should be terminated 3735 * immediately. 3736 */ 3737 cmd_sbp->fct_flags &= ~EMLXS_FCT_SEND_STATUS; 3738 3739 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 3740 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3741 3742 #ifdef FCT_API_TRACE 3743 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3744 "fct_queue_cmd_for_termination:2 %p: x%x", 3745 fct_cmd, fct_cmd->cmd_comp_status); 3746 #endif /* FCT_API_TRACE */ 3747 3748 MODSYM(fct_queue_cmd_for_termination) (fct_cmd, 3749 FCT_ABTS_RECEIVED); 3750 3751 break; 3752 } 3753 3754 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3755 EMLXS_FCT_PKT_FCPRSP_COMPLETE); 3756 3757 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3758 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3759 3760 #ifdef FCT_API_TRACE 3761 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3762 "fct_send_response_done:2 %p: x%x", 3763 fct_cmd, fct_cmd->cmd_comp_status); 3764 #else 3765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3766 "emlxs_fct_pkt_comp: fct_send_response_done. dbuf=%p", 3767 sbp->fct_buf); 3768 #endif /* FCT_API_TRACE */ 3769 3770 TGTPORTSTAT.FctOutstandingIO--; 3771 3772 MODSYM(fct_send_response_done) (fct_cmd, 3773 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3774 3775 break; 3776 3777 case FCT_CMD_RCVD_ELS: 3778 3779 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3780 EMLXS_FCT_PKT_ELSRSP_COMPLETE); 3781 3782 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3783 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3784 3785 #ifdef FCT_API_TRACE 3786 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3787 "fct_send_response_done:3 %p: x%x", 3788 fct_cmd, fct_cmd->cmd_comp_status); 3789 #endif /* FCT_API_TRACE */ 3790 3791 MODSYM(fct_send_response_done) (fct_cmd, 3792 fct_cmd->cmd_comp_status, FCT_IOF_FCA_DONE); 3793 3794 break; 3795 3796 case FCT_CMD_SOL_ELS: 3797 3798 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3799 EMLXS_FCT_PKT_ELSCMD_COMPLETE); 3800 3801 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 3802 3803 if (fct_els->els_resp_payload) { 3804 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, 3805 pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL); 3806 3807 bcopy((uint8_t *)pkt->pkt_resp, 3808 (uint8_t *)fct_els->els_resp_payload, 3809 fct_els->els_resp_size); 3810 } 3811 3812 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3813 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3814 3815 #ifdef FCT_API_TRACE 3816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3817 "fct_send_cmd_done:1 %p: x%x", 3818 fct_cmd, fct_cmd->cmd_comp_status); 3819 #endif /* FCT_API_TRACE */ 3820 3821 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, 3822 FCT_IOF_FCA_DONE); 3823 3824 break; 3825 3826 case FCT_CMD_SOL_CT: 3827 3828 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 3829 EMLXS_FCT_PKT_CTCMD_COMPLETE); 3830 3831 fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific; 3832 3833 if (fct_ct->ct_resp_payload) { 3834 EMLXS_MPDATA_SYNC(pkt->pkt_resp_dma, 0, 3835 pkt->pkt_rsplen, DDI_DMA_SYNC_FORKERNEL); 3836 3837 bcopy((uint8_t *)pkt->pkt_resp, 3838 (uint8_t *)fct_ct->ct_resp_payload, 3839 fct_ct->ct_resp_size); 3840 } 3841 3842 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3843 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3844 3845 #ifdef FCT_API_TRACE 3846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3847 "fct_send_cmd_done:2 %p: x%x", 3848 fct_cmd, fct_cmd->cmd_comp_status); 3849 #endif /* FCT_API_TRACE */ 3850 3851 MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, 3852 FCT_IOF_FCA_DONE); 3853 3854 break; 3855 3856 default: 3857 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3858 "emlxs_fct_pkt_comp: Invalid cmd type found. type=%x", 3859 fct_cmd->cmd_type); 3860 3861 emlxs_fct_cmd_done(port, fct_cmd, EMLXS_FCT_IO_DONE); 3862 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3863 3864 break; 3865 } 3866 3867 emlxs_pkt_free(pkt); 3868 return; 3869 3870 } /* emlxs_fct_pkt_comp() */ 3871 3872 3873 static void 3874 emlxs_fct_abort_pkt_comp(fc_packet_t *pkt) 3875 { 3876 #ifdef FCT_API_TRACE_11 3877 emlxs_buf_t *sbp; 3878 IOCBQ *iocbq; 3879 IOCB *iocb; 3880 3881 sbp = PKT2PRIV(pkt); 3882 iocbq = &sbp->iocbq; 3883 iocb = &iocbq->iocb; 3884 3885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3886 "emlxs_fct_handle_abort: %p: xri=%x status=%x", iocb->ULPCONTEXT, 3887 iocb->ULPCOMMAND, iocb->ULPSTATUS); 3888 #endif /* FCT_API_TRACE */ 3889 3890 emlxs_pkt_free(pkt); 3891 return; 3892 3893 } /* emlxs_fct_abort_pkt_comp() */ 3894 3895 3896 /* COMSTAR ENTER POINT (INDIRECT) */ 3897 static fct_status_t 3898 emlxs_fct_send_els_cmd(fct_cmd_t *fct_cmd) 3899 { 3900 emlxs_port_t *port = 3901 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 3902 emlxs_hba_t *hba = HBA; 3903 uint32_t did; 3904 fct_els_t *fct_els; 3905 fc_packet_t *pkt; 3906 emlxs_buf_t *cmd_sbp; 3907 fct_status_t rval; 3908 3909 did = fct_cmd->cmd_rportid; 3910 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 3911 3912 if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_req_size, 3913 fct_els->els_resp_size, 0, KM_NOSLEEP))) { 3914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 3915 "emlxs_fct_send_els_cmd: Unable to allocate packet."); 3916 3917 return (FCT_BUSY); 3918 } 3919 3920 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_ELS_REQ); 3921 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3922 3923 cmd_sbp->channel = &hba->chan[hba->channel_els]; 3924 cmd_sbp->fct_type = EMLXS_FCT_ELS_REQ; 3925 3926 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 3927 cmd_sbp->fct_pkt = pkt; 3928 3929 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 3930 pkt->pkt_timeout = 3931 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 3932 pkt->pkt_comp = emlxs_fct_pkt_comp; 3933 3934 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3935 "emlxs_fct_send_els_cmd: pkt_timeout=%d ratov=%d", 3936 pkt->pkt_timeout, hba->fc_ratov); 3937 3938 /* Build the fc header */ 3939 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 3940 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ; 3941 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 3942 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 3943 pkt->pkt_cmd_fhdr.f_ctl = 3944 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 3945 pkt->pkt_cmd_fhdr.seq_id = 0; 3946 pkt->pkt_cmd_fhdr.df_ctl = 0; 3947 pkt->pkt_cmd_fhdr.seq_cnt = 0; 3948 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 3949 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 3950 pkt->pkt_cmd_fhdr.ro = 0; 3951 3952 /* Copy the cmd payload */ 3953 bcopy((uint8_t *)fct_els->els_req_payload, (uint8_t *)pkt->pkt_cmd, 3954 fct_els->els_req_size); 3955 3956 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 3957 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING); 3958 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3959 3960 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 3961 3962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 3963 "emlxs_fct_send_els_cmd: Unable to send packet."); 3964 3965 /* Reacquire ownership of the fct_cmd */ 3966 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 3967 if (rval) { 3968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 3969 "emlxs_fct_send_els_cmd: " 3970 "Unable to reacquire fct_cmd."); 3971 return (rval); 3972 } 3973 /* mutex_enter(&cmd_sbp->fct_mtx); */ 3974 3975 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 3976 /* mutex_exit(&cmd_sbp->fct_mtx); */ 3977 3978 return (FCT_BUSY); 3979 } 3980 3981 return (FCT_SUCCESS); 3982 3983 } /* emlxs_fct_send_els_cmd() */ 3984 3985 3986 /* cmd_sbp->fct_mtx must be held to enter */ 3987 /* cmd_sbp->fct_mtx must be released before exiting */ 3988 static fct_status_t 3989 emlxs_fct_send_els_rsp(fct_cmd_t *fct_cmd) 3990 { 3991 emlxs_port_t *port = 3992 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 3993 emlxs_hba_t *hba = HBA; 3994 uint32_t did; 3995 fct_els_t *fct_els; 3996 fc_packet_t *pkt; 3997 emlxs_buf_t *cmd_sbp; 3998 fct_status_t rval; 3999 4000 fct_els = (fct_els_t *)fct_cmd->cmd_specific; 4001 did = fct_cmd->cmd_rportid; 4002 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4003 4004 if (!(pkt = emlxs_pkt_alloc(port, fct_els->els_resp_size, 0, 0, 4005 KM_NOSLEEP))) { 4006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4007 "emlxs_fct_send_els_rsp: Unable to allocate packet."); 4008 4009 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 4010 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4011 4012 return (FCT_FAILURE); 4013 } 4014 4015 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_SEND_ELS_RSP); 4016 4017 cmd_sbp->fct_type = EMLXS_FCT_ELS_RSP; 4018 4019 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 4020 cmd_sbp->fct_pkt = pkt; 4021 4022 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 4023 pkt->pkt_timeout = 4024 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4025 pkt->pkt_comp = emlxs_fct_pkt_comp; 4026 4027 /* Build the fc header */ 4028 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 4029 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP; 4030 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 4031 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 4032 pkt->pkt_cmd_fhdr.f_ctl = 4033 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 4034 pkt->pkt_cmd_fhdr.seq_id = 0; 4035 pkt->pkt_cmd_fhdr.df_ctl = 0; 4036 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4037 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 4038 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 4039 pkt->pkt_cmd_fhdr.ro = 0; 4040 4041 /* Copy the resp payload to pkt_cmd buffer */ 4042 bcopy((uint8_t *)fct_els->els_resp_payload, (uint8_t *)pkt->pkt_cmd, 4043 fct_els->els_resp_size); 4044 4045 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 4046 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_RSP_PENDING); 4047 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4048 4049 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4050 4051 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4052 "emlxs_fct_send_els_rsp: Unable to send packet."); 4053 4054 /* Reacquire ownership of the fct_cmd */ 4055 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 4056 if (rval) { 4057 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4058 "emlxs_fct_send_els_rsp: " 4059 "Unable to reacquire fct_cmd."); 4060 return (rval); 4061 } 4062 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4063 4064 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); 4065 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4066 4067 return (FCT_FAILURE); 4068 } 4069 4070 return (FCT_SUCCESS); 4071 4072 } /* emlxs_fct_send_els_rsp() */ 4073 4074 4075 /* COMSTAR ENTER POINT (INDIRECT) */ 4076 static fct_status_t 4077 emlxs_fct_send_ct_cmd(fct_cmd_t *fct_cmd) 4078 { 4079 emlxs_port_t *port = 4080 (emlxs_port_t *)fct_cmd->cmd_port->port_fca_private; 4081 emlxs_hba_t *hba = HBA; 4082 uint32_t did; 4083 fct_sol_ct_t *fct_ct; 4084 fc_packet_t *pkt; 4085 emlxs_buf_t *cmd_sbp; 4086 fct_status_t rval; 4087 4088 did = fct_cmd->cmd_rportid; 4089 fct_ct = (fct_sol_ct_t *)fct_cmd->cmd_specific; 4090 4091 if (!(pkt = emlxs_pkt_alloc(port, fct_ct->ct_req_size, 4092 fct_ct->ct_resp_size, 0, KM_NOSLEEP))) { 4093 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4094 "emlxs_fct_send_ct_cmd: Unable to allocate packet."); 4095 return (FCT_BUSY); 4096 } 4097 4098 cmd_sbp = emlxs_fct_cmd_init(port, fct_cmd, EMLXS_FCT_SEND_CT_REQ); 4099 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4100 4101 cmd_sbp->channel = &hba->chan[hba->channel_ct]; 4102 cmd_sbp->fct_type = EMLXS_FCT_CT_REQ; 4103 4104 (void) emlxs_fct_pkt_init(port, fct_cmd, pkt); 4105 cmd_sbp->fct_pkt = pkt; 4106 4107 pkt->pkt_tran_type = FC_PKT_EXCHANGE; 4108 pkt->pkt_timeout = 4109 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4110 pkt->pkt_comp = emlxs_fct_pkt_comp; 4111 4112 /* Build the fc header */ 4113 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); 4114 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL; 4115 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 4116 pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES; 4117 pkt->pkt_cmd_fhdr.f_ctl = 4118 F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 4119 pkt->pkt_cmd_fhdr.seq_id = 0; 4120 pkt->pkt_cmd_fhdr.df_ctl = 0; 4121 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4122 pkt->pkt_cmd_fhdr.ox_id = 0xFFFF; 4123 pkt->pkt_cmd_fhdr.rx_id = 0xFFFF; 4124 pkt->pkt_cmd_fhdr.ro = 0; 4125 4126 /* Copy the cmd payload */ 4127 bcopy((uint8_t *)fct_ct->ct_req_payload, (uint8_t *)pkt->pkt_cmd, 4128 fct_ct->ct_req_size); 4129 4130 cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; 4131 emlxs_fct_cmd_release(port, fct_cmd, EMLXS_FCT_REQ_PENDING); 4132 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4133 4134 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4135 4136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4137 "emlxs_fct_send_ct_cmd: Unable to send packet."); 4138 4139 /* Reacquire ownership of the fct_cmd */ 4140 rval = emlxs_fct_cmd_acquire(port, fct_cmd, 0); 4141 if (rval) { 4142 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4143 "emlxs_fct_send_ct_cmd: " 4144 "Unable to reacquire fct_cmd."); 4145 4146 return (rval); 4147 } 4148 /* mutex_enter(&cmd_sbp->fct_mtx); */ 4149 4150 emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_OWNED); 4151 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4152 4153 return (FCT_BUSY); 4154 } 4155 4156 return (FCT_SUCCESS); 4157 4158 } /* emlxs_fct_send_ct_cmd() */ 4159 4160 4161 /* cmd_sbp->fct_mtx must be held to enter */ 4162 static uint32_t 4163 emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp) 4164 { 4165 emlxs_hba_t *hba = HBA; 4166 NODELIST *nlp; 4167 fc_packet_t *pkt; 4168 emlxs_buf_t *sbp; 4169 emlxs_buf_t *iocb_sbp; 4170 uint8_t channelno; 4171 CHANNEL *cp; 4172 IOCBQ *iocbq; 4173 IOCBQ *next; 4174 IOCBQ *prev; 4175 uint32_t found; 4176 uint32_t pkt_flags; 4177 4178 /* Check the transmit queue */ 4179 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 4180 4181 /* The IOCB could point to a cmd_sbp (no packet) or a sbp (packet) */ 4182 pkt = cmd_sbp->fct_pkt; 4183 if (pkt) { 4184 sbp = PKT2PRIV(pkt); 4185 if (sbp == NULL) { 4186 goto done; 4187 } 4188 iocb_sbp = sbp; 4189 iocbq = &sbp->iocbq; 4190 pkt_flags = sbp->pkt_flags; 4191 } else { 4192 sbp = NULL; 4193 iocb_sbp = cmd_sbp; 4194 iocbq = &cmd_sbp->iocbq; 4195 pkt_flags = cmd_sbp->pkt_flags; 4196 } 4197 4198 nlp = (NODELIST *)cmd_sbp->node; 4199 cp = (CHANNEL *)cmd_sbp->channel; 4200 channelno = (cp) ? cp->channelno : 0; 4201 4202 if (pkt_flags & PACKET_IN_TXQ) { 4203 /* Find it on the queue */ 4204 found = 0; 4205 if (iocbq->flag & IOCB_PRIORITY) { 4206 /* Search the priority queue */ 4207 prev = NULL; 4208 next = (IOCBQ *)nlp->nlp_ptx[channelno].q_first; 4209 4210 while (next) { 4211 if (next == iocbq) { 4212 /* Remove it */ 4213 if (prev) { 4214 prev->next = iocbq->next; 4215 } 4216 4217 if (nlp->nlp_ptx[channelno].q_last == 4218 (void *)iocbq) { 4219 nlp->nlp_ptx[channelno].q_last = 4220 (void *)prev; 4221 } 4222 4223 if (nlp->nlp_ptx[channelno].q_first == 4224 (void *)iocbq) { 4225 nlp->nlp_ptx[channelno]. 4226 q_first = 4227 (void *)iocbq->next; 4228 } 4229 4230 nlp->nlp_ptx[channelno].q_cnt--; 4231 iocbq->next = NULL; 4232 found = 1; 4233 break; 4234 } 4235 4236 prev = next; 4237 next = next->next; 4238 } 4239 } else { 4240 /* Search the normal queue */ 4241 prev = NULL; 4242 next = (IOCBQ *)nlp->nlp_tx[channelno].q_first; 4243 4244 while (next) { 4245 if (next == iocbq) { 4246 /* Remove it */ 4247 if (prev) { 4248 prev->next = iocbq->next; 4249 } 4250 4251 if (nlp->nlp_tx[channelno].q_last == 4252 (void *)iocbq) { 4253 nlp->nlp_tx[channelno].q_last = 4254 (void *)prev; 4255 } 4256 4257 if (nlp->nlp_tx[channelno].q_first == 4258 (void *)iocbq) { 4259 nlp->nlp_tx[channelno].q_first = 4260 (void *)iocbq->next; 4261 } 4262 4263 nlp->nlp_tx[channelno].q_cnt--; 4264 iocbq->next = NULL; 4265 found = 1; 4266 break; 4267 } 4268 4269 prev = next; 4270 next = (IOCBQ *)next->next; 4271 } 4272 } 4273 4274 if (!found) { 4275 goto done; 4276 } 4277 4278 /* Check if node still needs servicing */ 4279 if ((nlp->nlp_ptx[channelno].q_first) || 4280 (nlp->nlp_tx[channelno].q_first && 4281 !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 4282 4283 /* 4284 * If this is the base node, don't shift the pointers 4285 */ 4286 /* We want to drain the base node before moving on */ 4287 if (!nlp->nlp_base) { 4288 /* Shift channel queue pointers to next node */ 4289 cp->nodeq.q_last = (void *)nlp; 4290 cp->nodeq.q_first = nlp->nlp_next[channelno]; 4291 } 4292 } else { 4293 /* Remove node from channel queue */ 4294 4295 /* If this is the last node on list */ 4296 if (cp->nodeq.q_last == (void *)nlp) { 4297 cp->nodeq.q_last = NULL; 4298 cp->nodeq.q_first = NULL; 4299 cp->nodeq.q_cnt = 0; 4300 } else { 4301 /* Remove node from head */ 4302 cp->nodeq.q_first = nlp->nlp_next[channelno]; 4303 ((NODELIST *)cp->nodeq.q_last)-> 4304 nlp_next[channelno] = cp->nodeq.q_first; 4305 cp->nodeq.q_cnt--; 4306 } 4307 4308 /* Clear node */ 4309 nlp->nlp_next[channelno] = NULL; 4310 } 4311 4312 /* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */ 4313 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4314 hba->fc_table[iocb_sbp->iotag] = NULL; 4315 emlxs_sli4_free_xri(hba, iocb_sbp, iocb_sbp->xp); 4316 } else { 4317 (void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0); 4318 } 4319 4320 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 4321 4322 if (pkt) { 4323 emlxs_pkt_free(pkt); 4324 cmd_sbp->fct_pkt = NULL; 4325 } 4326 return (1); 4327 } 4328 done: 4329 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 4330 return (0); 4331 4332 } /* emlxs_fct_pkt_abort_txq() */ 4333 4334 4335 /* COMSTAR ENTER POINT */ 4336 /* FCT_NOT_FOUND & FCT_ABORT_SUCCESS indicates IO is done */ 4337 /* FCT_SUCCESS indicates abort will occur asyncronously */ 4338 static fct_status_t 4339 emlxs_fct_abort(fct_local_port_t *fct_port, fct_cmd_t *fct_cmd, 4340 uint32_t flags) 4341 { 4342 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 4343 emlxs_hba_t *hba = HBA; 4344 emlxs_buf_t *cmd_sbp; 4345 emlxs_buf_t *cmd_sbp2; 4346 emlxs_buf_t *prev; 4347 fc_packet_t *pkt; 4348 emlxs_buf_t *sbp = NULL; 4349 kmutex_t *fct_mtx; 4350 uint32_t fct_state; 4351 4352 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4353 fct_mtx = &cmd_sbp->fct_mtx; 4354 4355 top: 4356 4357 /* Sanity check */ 4358 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 4359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4360 "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd); 4361 4362 return (FCT_NOT_FOUND); 4363 } 4364 4365 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 4366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4367 "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p", 4368 cmd_sbp); 4369 4370 return (FCT_NOT_FOUND); 4371 } 4372 4373 if (mutex_tryenter(fct_mtx) == 0) { 4374 /* 4375 * This code path handles a race condition if 4376 * an IO completes, in emlxs_fct_handle_fcp_event(), 4377 * and we get an abort at the same time. 4378 */ 4379 delay(drv_usectohz(100000)); /* 100 msec */ 4380 goto top; 4381 } 4382 /* At this point, we have entered the mutex */ 4383 4384 /* Sanity check */ 4385 if ((fct_cmd->cmd_oxid == 0) && (fct_cmd->cmd_rxid == 0)) { 4386 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4387 "emlxs_fct_abort: Bad fct_cmd=%p.", fct_cmd); 4388 4389 mutex_exit(fct_mtx); 4390 return (FCT_NOT_FOUND); 4391 } 4392 4393 if (!(cmd_sbp->pkt_flags & PACKET_VALID)) { 4394 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4395 "emlxs_fct_abort: Pkt invalid. cmd_sbp=%p", 4396 cmd_sbp); 4397 4398 mutex_exit(fct_mtx); 4399 return (FCT_NOT_FOUND); 4400 } 4401 4402 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4403 "emlxs_fct_abort: hbastate=%x. " 4404 "xid=%x,%x cmd_sbp=%p fctstate=%d flags=%x,%x,%x", 4405 hba->state, fct_cmd->cmd_oxid, fct_cmd->cmd_rxid, cmd_sbp, 4406 cmd_sbp->fct_state, flags, cmd_sbp->fct_flags, cmd_sbp->pkt_flags); 4407 4408 if (cmd_sbp->fct_flags & EMLXS_FCT_ABORT_INP) { 4409 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cmd_sbp->channel, 0); 4410 4411 /* If Abort is already in progress */ 4412 mutex_exit(fct_mtx); 4413 return (FCT_SUCCESS); 4414 } 4415 cmd_sbp->fct_flags |= EMLXS_FCT_ABORT_INP; 4416 4417 if (flags & FCT_IOF_FORCE_FCA_DONE) { 4418 fct_cmd->cmd_handle = 0; 4419 } 4420 4421 TGTPORTSTAT.FctAbortSent++; 4422 4423 switch (cmd_sbp->fct_state) { 4424 /* These are currently owned by COMSTAR. */ 4425 /* They were last processed by emlxs_fct_cmd_post() */ 4426 /* We have NO exchange resources associated with this IO. */ 4427 case EMLXS_FCT_OWNED: 4428 goto abort_done; 4429 4430 /* These are on the unsol waitQ in the driver */ 4431 case EMLXS_FCT_CMD_WAITQ: 4432 /* Find and remove it */ 4433 mutex_enter(&EMLXS_PORT_LOCK); 4434 cmd_sbp2 = port->fct_wait_head; 4435 prev = NULL; 4436 while (cmd_sbp2) { 4437 if (cmd_sbp2 == cmd_sbp) { 4438 /* Remove it */ 4439 if (prev) { 4440 prev->next = cmd_sbp2->next; 4441 } 4442 4443 if (port->fct_wait_head == cmd_sbp2) { 4444 port->fct_wait_head = cmd_sbp2->next; 4445 } 4446 4447 if (port->fct_wait_tail == cmd_sbp2) { 4448 port->fct_wait_tail = prev; 4449 } 4450 4451 cmd_sbp2->next = NULL; 4452 break; 4453 } 4454 prev = cmd_sbp2; 4455 cmd_sbp2 = cmd_sbp2->next; 4456 } 4457 mutex_exit(&EMLXS_PORT_LOCK); 4458 4459 /*FALLTHROUGH*/ 4460 4461 /* These are currently owned by COMSTAR. */ 4462 /* They were last processed by emlxs_fct_cmd_post() */ 4463 /* We have residual exchange resources associated with this IO */ 4464 case EMLXS_FCT_CMD_POSTED: 4465 switch (fct_cmd->cmd_type) { 4466 case FCT_CMD_FCP_XCHG: /* Unsol */ 4467 TGTPORTSTAT.FctOutstandingIO--; 4468 emlxs_abort_fct_exchange(hba, port, fct_cmd->cmd_rxid); 4469 break; 4470 4471 case FCT_CMD_RCVD_ELS: /* Unsol */ 4472 emlxs_abort_els_exchange(hba, port, fct_cmd->cmd_rxid); 4473 break; 4474 } 4475 4476 goto abort_done; 4477 4478 /* These are active in the driver */ 4479 /* They were last processed by emlxs_fct_cmd_release() */ 4480 case EMLXS_FCT_RSP_PENDING: 4481 case EMLXS_FCT_REQ_PENDING: 4482 case EMLXS_FCT_REG_PENDING: 4483 case EMLXS_FCT_DATA_PENDING: 4484 case EMLXS_FCT_STATUS_PENDING: 4485 4486 /* Abort anything pending */ 4487 if (emlxs_fct_pkt_abort_txq(port, cmd_sbp)) { 4488 4489 if (fct_cmd->cmd_type == FCT_CMD_FCP_XCHG) { 4490 TGTPORTSTAT.FctOutstandingIO--; 4491 } 4492 4493 goto abort_done; 4494 } 4495 4496 /* If we're not online, then all IO will be flushed anyway */ 4497 if (!(hba->flag & FC_ONLINE_MODE)) { 4498 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4499 "emlxs_fct_abort: Not online. fct_cmd=%p.", 4500 fct_cmd); 4501 4502 emlxs_fct_cmd_release(port, fct_cmd, 0); 4503 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4504 4505 /* The cmd will be aborted on the */ 4506 /* next emlxs_fct_cmd_acquire */ 4507 /* because EMLXS_FCT_ABORT_INP is set. */ 4508 break; 4509 } 4510 4511 /* Try to send abort request */ 4512 if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) { 4513 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4514 "emlxs_fct_abort: Unable to allocate packet. " 4515 "fct_cmd=%p", 4516 fct_cmd); 4517 4518 emlxs_fct_cmd_release(port, fct_cmd, 0); 4519 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4520 4521 /* The cmd will be aborted on the */ 4522 /* next emlxs_fct_cmd_acquire anyway */ 4523 /* because EMLXS_FCT_ABORT_INP is set. */ 4524 break; 4525 } 4526 4527 sbp = emlxs_fct_pkt_init(port, fct_cmd, pkt); 4528 4529 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 4530 pkt->pkt_timeout = 4531 ((2 * hba->fc_ratov) < 30) ? 30 : (2 * hba->fc_ratov); 4532 pkt->pkt_comp = emlxs_fct_abort_pkt_comp; 4533 4534 /* Build the fc header */ 4535 pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(fct_cmd->cmd_rportid); 4536 pkt->pkt_cmd_fhdr.r_ctl = R_CTL_STATUS; 4537 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 4538 pkt->pkt_cmd_fhdr.type = FC_TYPE_BASIC_LS; 4539 pkt->pkt_cmd_fhdr.f_ctl = 4540 (F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ); 4541 pkt->pkt_cmd_fhdr.seq_id = 0; 4542 pkt->pkt_cmd_fhdr.df_ctl = 0; 4543 pkt->pkt_cmd_fhdr.seq_cnt = 0; 4544 pkt->pkt_cmd_fhdr.ox_id = fct_cmd->cmd_oxid; 4545 pkt->pkt_cmd_fhdr.rx_id = fct_cmd->cmd_rxid; 4546 pkt->pkt_cmd_fhdr.ro = 0; 4547 4548 cmd_sbp->fct_cmd = fct_cmd; 4549 cmd_sbp->abort_attempts++; 4550 4551 /* Now disassociate the sbp / pkt from the fct_cmd */ 4552 sbp->fct_cmd = NULL; 4553 4554 if (hba->state >= FC_LINK_UP) { 4555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4556 "emlxs_fct_abort: ABORT: %p xri x%x", 4557 fct_cmd, fct_cmd->cmd_rxid); 4558 4559 fct_state = EMLXS_FCT_ABORT_PENDING; 4560 4561 } else { 4562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4563 "emlxs_fct_abort: CLOSE: %p xri x%x", 4564 fct_cmd, fct_cmd->cmd_rxid); 4565 4566 fct_state = EMLXS_FCT_CLOSE_PENDING; 4567 } 4568 4569 emlxs_fct_cmd_release(port, fct_cmd, fct_state); 4570 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4571 4572 if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { 4573 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4574 "emlxs_fct_abort: Unable to send abort packet."); 4575 4576 emlxs_pkt_free(pkt); 4577 4578 /* The cmd will be aborted on the */ 4579 /* next emlxs_fct_cmd_acquire anyway */ 4580 /* because EMLXS_FCT_ABORT_INP is set. */ 4581 } 4582 4583 break; 4584 4585 default: 4586 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4587 "emlxs_fct_abort: Unexpected fct_state. " 4588 "fct_cmd=%p state=%x", 4589 fct_cmd, cmd_sbp->fct_state); 4590 4591 emlxs_fct_cmd_release(port, fct_cmd, 0); 4592 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4593 4594 /* The cmd will be aborted on the */ 4595 /* next emlxs_fct_cmd_acquire anyway */ 4596 /* because EMLXS_FCT_ABORT_INP is set. */ 4597 4598 } /* switch */ 4599 4600 return (FCT_SUCCESS); 4601 4602 abort_done: 4603 4604 emlxs_fct_cmd_done(port, fct_cmd, 4605 EMLXS_FCT_ABORT_DONE); 4606 /* mutex_exit(&cmd_sbp->fct_mtx); */ 4607 4608 return (FCT_ABORT_SUCCESS); 4609 4610 } /* emlxs_fct_abort() */ 4611 4612 4613 extern void 4614 emlxs_fct_link_up(emlxs_port_t *port) 4615 { 4616 emlxs_hba_t *hba = HBA; 4617 4618 mutex_enter(&EMLXS_PORT_LOCK); 4619 4620 if (port->fct_port && 4621 (port->fct_flags & FCT_STATE_PORT_ONLINE) && 4622 !(port->fct_flags & FCT_STATE_LINK_UP)) { 4623 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4624 "emlxs_fct_link_up event."); 4625 4626 port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED; 4627 port->fct_flags |= FCT_STATE_LINK_UP; 4628 mutex_exit(&EMLXS_PORT_LOCK); 4629 4630 #ifdef FCT_API_TRACE 4631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4632 "fct_handle_event LINK_UP"); 4633 #endif /* FCT_API_TRACE */ 4634 MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_UP, 4635 0, 0); 4636 } else { 4637 if (!hba->ini_mode && 4638 !(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 4639 mutex_exit(&EMLXS_PORT_LOCK); 4640 4641 /* Take link down and hold it down */ 4642 (void) emlxs_reset_link(hba, 0, 1); 4643 } else { 4644 mutex_exit(&EMLXS_PORT_LOCK); 4645 } 4646 } 4647 4648 return; 4649 4650 } /* emlxs_fct_link_up() */ 4651 4652 4653 extern void 4654 emlxs_fct_link_down(emlxs_port_t *port) 4655 { 4656 emlxs_hba_t *hba = HBA; 4657 4658 mutex_enter(&EMLXS_PORT_LOCK); 4659 4660 if (port->fct_port && 4661 (port->fct_flags & FCT_STATE_PORT_ONLINE) && 4662 (port->fct_flags & FCT_STATE_LINK_UP)) { 4663 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4664 "emlxs_fct_link_down event."); 4665 4666 port->fct_flags &= ~FCT_STATE_LINK_UP_ACKED; 4667 port->fct_flags &= ~FCT_STATE_LINK_UP; 4668 mutex_exit(&EMLXS_PORT_LOCK); 4669 4670 #ifdef FCT_API_TRACE 4671 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4672 "fct_handle_event LINK_DOWN"); 4673 #endif /* FCT_API_TRACE */ 4674 4675 MODSYM(fct_handle_event) (port->fct_port, FCT_EVENT_LINK_DOWN, 4676 0, 0); 4677 } else { 4678 mutex_exit(&EMLXS_PORT_LOCK); 4679 } 4680 4681 return; 4682 4683 } /* emlxs_fct_link_down() */ 4684 4685 4686 /* DMA FUNCTIONS */ 4687 4688 fct_status_t 4689 emlxs_fct_dmem_init(emlxs_port_t *port) 4690 { 4691 emlxs_hba_t *hba = HBA; 4692 emlxs_fct_dmem_bucket_t *p; 4693 emlxs_fct_dmem_bctl_t *bctl; 4694 emlxs_fct_dmem_bctl_t *bc; 4695 emlxs_fct_dmem_bctl_t *prev; 4696 int32_t j; 4697 int32_t i; 4698 uint32_t total_mem; 4699 uint8_t *addr; 4700 uint8_t *host_addr; 4701 uint64_t dev_addr; 4702 ddi_dma_cookie_t cookie; 4703 uint32_t ncookie; 4704 uint32_t bsize; 4705 size_t len; 4706 char buf[64]; 4707 ddi_device_acc_attr_t acc; 4708 4709 bzero(&acc, sizeof (acc)); 4710 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 4711 acc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 4712 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 4713 4714 p = port->dmem_bucket; 4715 for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) { 4716 if (!p->dmem_nbufs) { 4717 continue; 4718 } 4719 4720 bctl = (emlxs_fct_dmem_bctl_t *)kmem_zalloc(p->dmem_nbufs * 4721 sizeof (emlxs_fct_dmem_bctl_t), KM_NOSLEEP); 4722 4723 if (bctl == NULL) { 4724 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4725 "emlxs_fct_dmem_init: Unable to allocate bctl."); 4726 goto alloc_bctl_failed; 4727 } 4728 4729 p->dmem_bctls_mem = bctl; 4730 4731 if (ddi_dma_alloc_handle(hba->dip, &emlxs_dma_attr_1sg, 4732 DDI_DMA_SLEEP, 0, &p->dmem_dma_handle) != DDI_SUCCESS) { 4733 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4734 "emlxs_fct_dmem_init: Unable to allocate handle."); 4735 goto alloc_handle_failed; 4736 } 4737 4738 total_mem = p->dmem_buf_size * p->dmem_nbufs; 4739 4740 if (ddi_dma_mem_alloc(p->dmem_dma_handle, total_mem, &acc, 4741 DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0, 4742 (caddr_t *)&addr, &len, 4743 &p->dmem_acc_handle) != DDI_SUCCESS) { 4744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4745 "emlxs_fct_dmem_init: Unable to allocate memory."); 4746 goto mem_alloc_failed; 4747 } 4748 4749 if (ddi_dma_addr_bind_handle(p->dmem_dma_handle, NULL, 4750 (caddr_t)addr, total_mem, 4751 DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0, 4752 &cookie, &ncookie) != DDI_SUCCESS) { 4753 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4754 "emlxs_fct_dmem_init: Unable to bind handle."); 4755 goto addr_bind_handle_failed; 4756 } 4757 4758 if (ncookie != 1) { 4759 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4760 "emlxs_fct_dmem_init: DMEM init failed."); 4761 goto dmem_init_failed; 4762 } 4763 (void) sprintf(buf, "%s%d_bucket%d mutex", DRIVER_NAME, 4764 hba->ddiinst, i); 4765 mutex_init(&p->dmem_lock, buf, MUTEX_DRIVER, 4766 (void *)hba->intr_arg); 4767 4768 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4769 "bufsize=%d cnt=%d", p->dmem_buf_size, p->dmem_nbufs); 4770 4771 host_addr = addr; 4772 dev_addr = (uint64_t)cookie.dmac_laddress; 4773 4774 p->dmem_host_addr = addr; 4775 p->dmem_dev_addr = dev_addr; 4776 p->dmem_bctl_free_list = bctl; 4777 p->dmem_nbufs_free = p->dmem_nbufs; 4778 bsize = p->dmem_buf_size; 4779 4780 for (j = 0; j < p->dmem_nbufs; j++) { 4781 stmf_data_buf_t *db; 4782 4783 db = MODSYM(stmf_alloc) (STMF_STRUCT_DATA_BUF, 0, 0); 4784 #ifdef FCT_API_TRACE 4785 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4786 "stmf_alloc data_buf %p", db); 4787 #endif /* FCT_API_TRACE */ 4788 if (db == NULL) { 4789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4790 "emlxs_fct_dmem_init: alloc failed."); 4791 goto dmem_init_failed; 4792 } 4793 db->db_port_private = bctl; 4794 db->db_sglist[0].seg_addr = host_addr; 4795 db->db_sglist[0].seg_length = bsize; 4796 db->db_buf_size = bsize; 4797 db->db_sglist_length = 1; 4798 4799 bctl->bctl_bucket = p; 4800 bctl->bctl_buf = db; 4801 bctl->bctl_dev_addr = dev_addr; 4802 4803 host_addr += bsize; 4804 dev_addr += bsize; 4805 4806 prev = bctl; 4807 bctl++; 4808 prev->bctl_next = bctl; 4809 } 4810 4811 prev->bctl_next = NULL; 4812 } 4813 4814 return (FCT_SUCCESS); 4815 4816 dmem_failure_loop: 4817 mutex_destroy(&p->dmem_lock); 4818 bc = bctl; 4819 while (bc) { 4820 #ifdef FCT_API_TRACE 4821 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4822 "stmf_free:3 %p", bctl->bctl_buf); 4823 #endif /* FCT_API_TRACE */ 4824 MODSYM(stmf_free) (bc->bctl_buf); 4825 bc = bc->bctl_next; 4826 } 4827 4828 dmem_init_failed: 4829 (void) ddi_dma_unbind_handle(p->dmem_dma_handle); 4830 4831 addr_bind_handle_failed: 4832 (void) ddi_dma_mem_free(&p->dmem_acc_handle); 4833 4834 mem_alloc_failed: 4835 (void) ddi_dma_free_handle(&p->dmem_dma_handle); 4836 4837 alloc_handle_failed: 4838 kmem_free(p->dmem_bctls_mem, 4839 p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t)); 4840 4841 alloc_bctl_failed: 4842 if (--i >= 0) { 4843 p = &port->dmem_bucket[i]; 4844 bctl = p->dmem_bctl_free_list; 4845 goto dmem_failure_loop; 4846 } 4847 4848 return (FCT_FAILURE); 4849 4850 } /* emlxs_fct_dmem_init() */ 4851 4852 4853 void 4854 emlxs_fct_dmem_fini(emlxs_port_t *port) 4855 { 4856 emlxs_fct_dmem_bucket_t *p; 4857 emlxs_fct_dmem_bctl_t *bctl; 4858 uint32_t i; 4859 4860 p = port->dmem_bucket; 4861 for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) { 4862 if (!p->dmem_nbufs) { 4863 continue; 4864 } 4865 4866 bctl = p->dmem_bctl_free_list; 4867 4868 while (bctl) { 4869 #ifdef FCT_API_TRACE 4870 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4871 "stmf_free:4 %p", bctl->bctl_buf); 4872 #endif /* FCT_API_TRACE */ 4873 MODSYM(stmf_free) (bctl->bctl_buf); 4874 bctl = bctl->bctl_next; 4875 } 4876 4877 bctl = p->dmem_bctl_free_list; 4878 4879 (void) ddi_dma_unbind_handle(p->dmem_dma_handle); 4880 (void) ddi_dma_mem_free(&p->dmem_acc_handle); 4881 (void) ddi_dma_free_handle(&p->dmem_dma_handle); 4882 4883 kmem_free(p->dmem_bctls_mem, 4884 (p->dmem_nbufs * sizeof (emlxs_fct_dmem_bctl_t))); 4885 mutex_destroy(&p->dmem_lock); 4886 } 4887 4888 bzero((uint8_t *)port->dmem_bucket, sizeof (port->dmem_bucket)); 4889 4890 return; 4891 4892 } /* emlxs_fct_dmem_fini() */ 4893 4894 4895 /* COMSTAR ENTER POINT */ 4896 /* ARGSUSED */ 4897 static stmf_data_buf_t * 4898 emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size, 4899 uint32_t *pminsize, uint32_t flags) 4900 { 4901 emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; 4902 emlxs_fct_dmem_bucket_t *p; 4903 emlxs_fct_dmem_bctl_t *bctl; 4904 uint32_t i; 4905 4906 if (size > FCT_DMEM_MAX_BUF_SIZE) { 4907 size = FCT_DMEM_MAX_BUF_SIZE; 4908 } 4909 4910 p = port->dmem_bucket; 4911 for (i = 0; i < FCT_MAX_BUCKETS; i++, p++) { 4912 if (!p->dmem_nbufs) { 4913 continue; 4914 } 4915 4916 if (p->dmem_buf_size >= size) { 4917 mutex_enter(&p->dmem_lock); 4918 if (p->dmem_nbufs_free) { 4919 if (p->dmem_buf_size < *pminsize) { 4920 *pminsize = p->dmem_buf_size; 4921 TGTPORTSTAT.FctNoBuffer++; 4922 4923 EMLXS_MSGF(EMLXS_CONTEXT, 4924 &emlxs_fct_api_msg, 4925 "emlxs_fct_dbuf_alloc: Failed(1)."); 4926 mutex_exit(&p->dmem_lock); 4927 return (NULL); 4928 } 4929 4930 bctl = p->dmem_bctl_free_list; 4931 if (bctl == NULL) { 4932 mutex_exit(&p->dmem_lock); 4933 continue; 4934 } 4935 4936 p->dmem_bctl_free_list = bctl->bctl_next; 4937 p->dmem_nbufs_free--; 4938 bctl->bctl_buf->db_data_size = size; 4939 mutex_exit(&p->dmem_lock); 4940 4941 #ifdef FCT_API_TRACE 4942 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4943 "emlx_fct_buf_alloc: bctl_buf %p: size %d", 4944 bctl->bctl_buf, size); 4945 #endif /* FCT_API_TRACE */ 4946 4947 return (bctl->bctl_buf); 4948 } 4949 mutex_exit(&p->dmem_lock); 4950 4951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, 4952 "emlx_fct_buf_alloc size %d Nothing free bck %d", 4953 size, i); 4954 } 4955 } 4956 4957 *pminsize = 0; 4958 TGTPORTSTAT.FctNoBuffer++; 4959 4960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4961 "emlxs_fct_dbuf_alloc: Failed(2)."); 4962 4963 return (NULL); 4964 4965 } /* emlxs_fct_dbuf_alloc() */ 4966 4967 4968 /* COMSTAR ENTER POINT */ 4969 /*ARGSUSED*/ 4970 static void 4971 emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf) 4972 { 4973 emlxs_fct_dmem_bctl_t *bctl = 4974 (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private; 4975 emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket; 4976 4977 #ifdef FCT_API_TRACE_1 4978 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 4979 "emlx_fct_buf_free %p", dbuf); 4980 #endif /* FCT_API_TRACE */ 4981 4982 mutex_enter(&p->dmem_lock); 4983 bctl->bctl_next = p->dmem_bctl_free_list; 4984 p->dmem_bctl_free_list = bctl; 4985 p->dmem_nbufs_free++; 4986 mutex_exit(&p->dmem_lock); 4987 4988 } /* emlxs_fct_dbuf_free() */ 4989 4990 4991 static void 4992 emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type) 4993 { 4994 emlxs_fct_dmem_bctl_t *bctl = 4995 (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private; 4996 emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket; 4997 4998 (void) ddi_dma_sync(p->dmem_dma_handle, 4999 (unsigned long)(bctl->bctl_dev_addr - p->dmem_dev_addr), 5000 dbuf->db_data_size, sync_type); 5001 5002 } /* emlxs_fct_dbuf_dma_sync() */ 5003 5004 5005 #endif /* SFCT_SUPPORT */ 5006