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