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