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