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