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