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 9 * http://www.opensource.org/licenses/cddl1.txt. 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 (c) 2004-2012 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 26 * Copyright 2020 RackTop Systems, Inc. 27 */ 28 29 #include <emlxs.h> 30 31 32 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 33 EMLXS_MSG_DEF(EMLXS_SLI4_C); 34 35 static int emlxs_sli4_init_extents(emlxs_hba_t *hba, 36 MAILBOXQ *mbq); 37 static uint32_t emlxs_sli4_read_status(emlxs_hba_t *hba); 38 39 static int emlxs_init_bootstrap_mb(emlxs_hba_t *hba); 40 41 static uint32_t emlxs_sli4_read_sema(emlxs_hba_t *hba); 42 43 static uint32_t emlxs_sli4_read_mbdb(emlxs_hba_t *hba); 44 45 static void emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint64_t phys, 46 boolean_t high); 47 48 static void emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint16_t qid, 49 uint_t posted, uint_t index); 50 51 static void emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint16_t qid, 52 uint_t count); 53 54 static void emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint16_t qid, 55 uint_t count); 56 57 static void emlxs_sli4_write_eqdb(emlxs_hba_t *hba, uint16_t qid, 58 uint32_t count, boolean_t arm); 59 static void emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint16_t qid, 60 uint32_t count, boolean_t arm); 61 62 static int emlxs_sli4_create_queues(emlxs_hba_t *hba, 63 MAILBOXQ *mbq); 64 static int emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, 65 MAILBOXQ *mbq); 66 static int emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, 67 MAILBOXQ *mbq); 68 69 static int emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq); 70 71 static int emlxs_sli4_map_hdw(emlxs_hba_t *hba); 72 73 static void emlxs_sli4_unmap_hdw(emlxs_hba_t *hba); 74 75 static int32_t emlxs_sli4_online(emlxs_hba_t *hba); 76 77 static void emlxs_sli4_offline(emlxs_hba_t *hba, 78 uint32_t reset_requested); 79 80 static uint32_t emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, 81 uint32_t skip_post, uint32_t quiesce); 82 static void emlxs_sli4_hba_kill(emlxs_hba_t *hba); 83 84 static uint32_t emlxs_sli4_hba_init(emlxs_hba_t *hba); 85 86 static uint32_t emlxs_sli4_bde_setup(emlxs_port_t *port, 87 emlxs_buf_t *sbp); 88 89 static void emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, 90 CHANNEL *cp, IOCBQ *iocb_cmd); 91 static uint32_t emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, 92 MAILBOXQ *mbq, int32_t flg, uint32_t tmo); 93 static uint32_t emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, 94 MAILBOXQ *mbq, int32_t flg, uint32_t tmo); 95 #ifdef SFCT_SUPPORT 96 static uint32_t emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, 97 emlxs_buf_t *cmd_sbp, int channel); 98 static uint32_t emlxs_sli4_fct_bde_setup(emlxs_port_t *port, 99 emlxs_buf_t *sbp); 100 #endif /* SFCT_SUPPORT */ 101 102 static uint32_t emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, 103 emlxs_buf_t *sbp, int ring); 104 static uint32_t emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, 105 emlxs_buf_t *sbp); 106 static uint32_t emlxs_sli4_prep_els_iocb(emlxs_port_t *port, 107 emlxs_buf_t *sbp); 108 static uint32_t emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, 109 emlxs_buf_t *sbp); 110 static void emlxs_sli4_poll_intr(emlxs_hba_t *hba); 111 static int32_t emlxs_sli4_intx_intr(char *arg); 112 113 #ifdef MSI_SUPPORT 114 static uint32_t emlxs_sli4_msi_intr(char *arg1, char *arg2); 115 #endif /* MSI_SUPPORT */ 116 117 static void emlxs_sli4_resource_free(emlxs_hba_t *hba); 118 119 static int emlxs_sli4_resource_alloc(emlxs_hba_t *hba); 120 extern void emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba); 121 122 static XRIobj_t *emlxs_sli4_alloc_xri(emlxs_port_t *port, 123 emlxs_buf_t *sbp, RPIobj_t *rpip, 124 uint32_t type); 125 static void emlxs_sli4_enable_intr(emlxs_hba_t *hba); 126 127 static void emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att); 128 129 static void emlxs_sli4_timer(emlxs_hba_t *hba); 130 131 static void emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba); 132 133 static void emlxs_sli4_gpio_timer_start(emlxs_hba_t *hba); 134 135 static void emlxs_sli4_gpio_timer_stop(emlxs_hba_t *hba); 136 137 static void emlxs_sli4_gpio_timer(void *arg); 138 139 static void emlxs_sli4_check_gpio(emlxs_hba_t *hba); 140 141 static uint32_t emlxs_sli4_fix_gpio(emlxs_hba_t *hba, 142 uint8_t *pin, uint8_t *pinval); 143 144 static uint32_t emlxs_sli4_fix_gpio_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq); 145 146 static void emlxs_sli4_poll_erratt(emlxs_hba_t *hba); 147 148 extern XRIobj_t *emlxs_sli4_reserve_xri(emlxs_port_t *port, 149 RPIobj_t *rpip, uint32_t type, uint16_t rx_id); 150 static int emlxs_check_hdw_ready(emlxs_hba_t *); 151 152 static uint32_t emlxs_sli4_reg_did(emlxs_port_t *port, 153 uint32_t did, SERV_PARM *param, 154 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, 155 IOCBQ *iocbq); 156 157 static uint32_t emlxs_sli4_unreg_node(emlxs_port_t *port, 158 emlxs_node_t *node, emlxs_buf_t *sbp, 159 fc_unsol_buf_t *ubp, IOCBQ *iocbq); 160 161 static void emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba, 162 CQE_ASYNC_t *cqe); 163 static void emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba, 164 CQE_ASYNC_t *cqe); 165 166 167 static uint16_t emlxs_sli4_rqid_to_index(emlxs_hba_t *hba, 168 uint16_t rqid); 169 static uint16_t emlxs_sli4_wqid_to_index(emlxs_hba_t *hba, 170 uint16_t wqid); 171 static uint16_t emlxs_sli4_cqid_to_index(emlxs_hba_t *hba, 172 uint16_t cqid); 173 174 /* Define SLI4 API functions */ 175 emlxs_sli_api_t emlxs_sli4_api = { 176 emlxs_sli4_map_hdw, 177 emlxs_sli4_unmap_hdw, 178 emlxs_sli4_online, 179 emlxs_sli4_offline, 180 emlxs_sli4_hba_reset, 181 emlxs_sli4_hba_kill, 182 emlxs_sli4_issue_iocb_cmd, 183 emlxs_sli4_issue_mbox_cmd, 184 #ifdef SFCT_SUPPORT 185 emlxs_sli4_prep_fct_iocb, 186 #else 187 NULL, 188 #endif /* SFCT_SUPPORT */ 189 emlxs_sli4_prep_fcp_iocb, 190 emlxs_sli4_prep_ip_iocb, 191 emlxs_sli4_prep_els_iocb, 192 emlxs_sli4_prep_ct_iocb, 193 emlxs_sli4_poll_intr, 194 emlxs_sli4_intx_intr, 195 emlxs_sli4_msi_intr, 196 emlxs_sli4_disable_intr, 197 emlxs_sli4_timer, 198 emlxs_sli4_poll_erratt, 199 emlxs_sli4_reg_did, 200 emlxs_sli4_unreg_node 201 }; 202 203 204 /* ************************************************************************** */ 205 206 static void 207 emlxs_sli4_set_default_params(emlxs_hba_t *hba) 208 { 209 emlxs_port_t *port = &PPORT; 210 211 bzero((char *)&hba->sli.sli4.param, sizeof (sli_params_t)); 212 213 hba->sli.sli4.param.ProtocolType = 0x3; /* FC/FCoE */ 214 215 hba->sli.sli4.param.SliHint2 = 0; 216 hba->sli.sli4.param.SliHint1 = 0; 217 hba->sli.sli4.param.IfType = 0; 218 hba->sli.sli4.param.SliFamily = 0; 219 hba->sli.sli4.param.Revision = 0x4; /* SLI4 */ 220 hba->sli.sli4.param.FT = 0; 221 222 hba->sli.sli4.param.EqeCntMethod = 0x1; /* Bit pattern */ 223 hba->sli.sli4.param.EqPageSize = 0x1; /* 4096 */ 224 hba->sli.sli4.param.EqeSize = 0x1; /* 4 byte */ 225 hba->sli.sli4.param.EqPageCnt = 8; 226 hba->sli.sli4.param.EqeCntMask = 0x1F; /* 256-4096 elements */ 227 228 hba->sli.sli4.param.CqeCntMethod = 0x1; /* Bit pattern */ 229 hba->sli.sli4.param.CqPageSize = 0x1; /* 4096 */ 230 hba->sli.sli4.param.CQV = 0; 231 hba->sli.sli4.param.CqeSize = 0x3; /* 16 byte */ 232 hba->sli.sli4.param.CqPageCnt = 4; 233 hba->sli.sli4.param.CqeCntMask = 0x70; /* 256-1024 elements */ 234 235 hba->sli.sli4.param.MqeCntMethod = 0x1; /* Bit pattern */ 236 hba->sli.sli4.param.MqPageSize = 0x1; /* 4096 */ 237 hba->sli.sli4.param.MQV = 0; 238 hba->sli.sli4.param.MqPageCnt = 8; 239 hba->sli.sli4.param.MqeCntMask = 0x0F; /* 16-128 elements */ 240 241 hba->sli.sli4.param.WqeCntMethod = 0; /* Page Count */ 242 hba->sli.sli4.param.WqPageSize = 0x1; /* 4096 */ 243 hba->sli.sli4.param.WQV = 0; 244 hba->sli.sli4.param.WqeSize = 0x5; /* 64 byte */ 245 hba->sli.sli4.param.WqPageCnt = 4; 246 hba->sli.sli4.param.WqeCntMask = 0x10; /* 256 elements */ 247 248 hba->sli.sli4.param.RqeCntMethod = 0; /* Page Count */ 249 hba->sli.sli4.param.RqPageSize = 0x1; /* 4096 */ 250 hba->sli.sli4.param.RQV = 0; 251 hba->sli.sli4.param.RqeSize = 0x2; /* 8 byte */ 252 hba->sli.sli4.param.RqPageCnt = 8; 253 hba->sli.sli4.param.RqDbWin = 1; 254 hba->sli.sli4.param.RqeCntMask = 0x100; /* 4096 elements */ 255 256 hba->sli.sli4.param.Loopback = 0xf; /* unsupported */ 257 hba->sli.sli4.param.PHWQ = 0; 258 hba->sli.sli4.param.PHON = 0; 259 hba->sli.sli4.param.TRIR = 0; 260 hba->sli.sli4.param.TRTY = 0; 261 hba->sli.sli4.param.TCCA = 0; 262 hba->sli.sli4.param.MWQE = 0; 263 hba->sli.sli4.param.ASSI = 0; 264 hba->sli.sli4.param.TERP = 0; 265 hba->sli.sli4.param.TGT = 0; 266 hba->sli.sli4.param.AREG = 0; 267 hba->sli.sli4.param.FBRR = 0; 268 hba->sli.sli4.param.SGLR = 1; 269 hba->sli.sli4.param.HDRR = 1; 270 hba->sli.sli4.param.EXT = 0; 271 hba->sli.sli4.param.FCOE = 1; 272 273 hba->sli.sli4.param.SgeLength = (64 * 1024); 274 hba->sli.sli4.param.SglAlign = 0x7 /* 4096 */; 275 hba->sli.sli4.param.SglPageSize = 0x1; /* 4096 */ 276 hba->sli.sli4.param.SglPageCnt = 2; 277 278 hba->sli.sli4.param.MinRqSize = 128; 279 hba->sli.sli4.param.MaxRqSize = 2048; 280 281 hba->sli.sli4.param.RPIMax = 0x3ff; 282 hba->sli.sli4.param.XRIMax = 0x3ff; 283 hba->sli.sli4.param.VFIMax = 0xff; 284 hba->sli.sli4.param.VPIMax = 0xff; 285 286 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 287 "Default SLI4 parameters set."); 288 289 } /* emlxs_sli4_set_default_params() */ 290 291 292 /* 293 * emlxs_sli4_online() 294 * 295 * This routine will start initialization of the SLI4 HBA. 296 */ 297 static int32_t 298 emlxs_sli4_online(emlxs_hba_t *hba) 299 { 300 emlxs_port_t *port = &PPORT; 301 emlxs_config_t *cfg; 302 emlxs_vpd_t *vpd; 303 MAILBOXQ *mbq = NULL; 304 MAILBOX4 *mb = NULL; 305 MATCHMAP *mp = NULL; 306 uint32_t i; 307 uint32_t j; 308 uint32_t rval = 0; 309 uint8_t *vpd_data; 310 uint32_t sli_mode; 311 uint8_t *outptr; 312 uint32_t status; 313 uint32_t fw_check; 314 uint32_t kern_update = 0; 315 emlxs_firmware_t hba_fw; 316 emlxs_firmware_t *fw; 317 uint16_t ssvid; 318 char buf[64]; 319 320 cfg = &CFG; 321 vpd = &VPD; 322 323 sli_mode = EMLXS_HBA_SLI4_MODE; 324 hba->sli_mode = sli_mode; 325 326 /* Set the fw_check flag */ 327 fw_check = cfg[CFG_FW_CHECK].current; 328 329 if ((fw_check & 0x04) || 330 (hba->fw_flag & FW_UPDATE_KERNEL)) { 331 kern_update = 1; 332 } 333 334 hba->mbox_queue_flag = 0; 335 hba->fc_edtov = FF_DEF_EDTOV; 336 hba->fc_ratov = FF_DEF_RATOV; 337 hba->fc_altov = FF_DEF_ALTOV; 338 hba->fc_arbtov = FF_DEF_ARBTOV; 339 340 /* Networking not supported */ 341 if (cfg[CFG_NETWORK_ON].current) { 342 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 343 "Networking is not supported in SLI4, turning it off"); 344 cfg[CFG_NETWORK_ON].current = 0; 345 } 346 347 hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current; 348 if (hba->chan_count > MAX_CHANNEL) { 349 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 350 "Max channels exceeded, dropping num-wq from %d to 1", 351 cfg[CFG_NUM_WQ].current); 352 cfg[CFG_NUM_WQ].current = 1; 353 hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current; 354 } 355 hba->channel_fcp = 0; /* First channel */ 356 357 /* Default channel for everything else is the last channel */ 358 hba->channel_ip = hba->chan_count - 1; 359 hba->channel_els = hba->chan_count - 1; 360 hba->channel_ct = hba->chan_count - 1; 361 362 hba->fc_iotag = 1; 363 hba->io_count = 0; 364 hba->channel_tx_count = 0; 365 366 /* Specific to ATTO G5 boards */ 367 if (hba->model_info.flags & EMLXS_GPIO_LEDS) { 368 /* Set hard-coded GPIO pins */ 369 if (hba->pci_function_number) { 370 hba->gpio_pin[EMLXS_GPIO_PIN_LO] = 27; 371 hba->gpio_pin[EMLXS_GPIO_PIN_HI] = 28; 372 hba->gpio_pin[EMLXS_GPIO_PIN_ACT] = 29; 373 hba->gpio_pin[EMLXS_GPIO_PIN_LASER] = 8; 374 } else { 375 hba->gpio_pin[EMLXS_GPIO_PIN_LO] = 13; 376 hba->gpio_pin[EMLXS_GPIO_PIN_HI] = 25; 377 hba->gpio_pin[EMLXS_GPIO_PIN_ACT] = 26; 378 hba->gpio_pin[EMLXS_GPIO_PIN_LASER] = 12; 379 } 380 } 381 382 /* Initialize the local dump region buffer */ 383 bzero(&hba->sli.sli4.dump_region, sizeof (MBUF_INFO)); 384 hba->sli.sli4.dump_region.size = EMLXS_DUMP_REGION_SIZE; 385 hba->sli.sli4.dump_region.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 386 hba->sli.sli4.dump_region.align = ddi_ptob(hba->dip, 1L); 387 388 (void) emlxs_mem_alloc(hba, &hba->sli.sli4.dump_region); 389 390 if (hba->sli.sli4.dump_region.virt == NULL) { 391 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 392 "Unable to allocate dump region buffer."); 393 394 return (ENOMEM); 395 } 396 397 /* 398 * Get a buffer which will be used repeatedly for mailbox commands 399 */ 400 mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); 401 402 mb = (MAILBOX4 *)mbq; 403 404 reset: 405 /* Reset & Initialize the adapter */ 406 if (emlxs_sli4_hba_init(hba)) { 407 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 408 "Unable to init hba."); 409 410 rval = EIO; 411 goto failed1; 412 } 413 414 #ifdef FMA_SUPPORT 415 /* Access handle validation */ 416 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 417 case SLI_INTF_IF_TYPE_6: 418 if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 419 != DDI_FM_OK) || 420 (emlxs_fm_check_acc_handle(hba, 421 hba->sli.sli4.bar0_acc_handle) != DDI_FM_OK) || 422 (emlxs_fm_check_acc_handle(hba, 423 hba->sli.sli4.bar1_acc_handle) != DDI_FM_OK)) { 424 EMLXS_MSGF(EMLXS_CONTEXT, 425 &emlxs_invalid_access_handle_msg, NULL); 426 427 rval = EIO; 428 goto failed1; 429 } 430 break; 431 case SLI_INTF_IF_TYPE_2: 432 if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 433 != DDI_FM_OK) || 434 (emlxs_fm_check_acc_handle(hba, 435 hba->sli.sli4.bar0_acc_handle) != DDI_FM_OK)) { 436 EMLXS_MSGF(EMLXS_CONTEXT, 437 &emlxs_invalid_access_handle_msg, NULL); 438 439 rval = EIO; 440 goto failed1; 441 } 442 break; 443 default : 444 if ((emlxs_fm_check_acc_handle(hba, 445 hba->pci_acc_handle) != DDI_FM_OK) || 446 (emlxs_fm_check_acc_handle(hba, 447 hba->sli.sli4.bar1_acc_handle) != DDI_FM_OK) || 448 (emlxs_fm_check_acc_handle(hba, 449 hba->sli.sli4.bar2_acc_handle) != DDI_FM_OK)) { 450 EMLXS_MSGF(EMLXS_CONTEXT, 451 &emlxs_invalid_access_handle_msg, NULL); 452 453 rval = EIO; 454 goto failed1; 455 } 456 break; 457 } 458 #endif /* FMA_SUPPORT */ 459 460 /* 461 * Setup and issue mailbox READ REV command 462 */ 463 vpd->opFwRev = 0; 464 vpd->postKernRev = 0; 465 vpd->sli1FwRev = 0; 466 vpd->sli2FwRev = 0; 467 vpd->sli3FwRev = 0; 468 vpd->sli4FwRev = 0; 469 470 vpd->postKernName[0] = 0; 471 vpd->opFwName[0] = 0; 472 vpd->sli1FwName[0] = 0; 473 vpd->sli2FwName[0] = 0; 474 vpd->sli3FwName[0] = 0; 475 vpd->sli4FwName[0] = 0; 476 477 vpd->opFwLabel[0] = 0; 478 vpd->sli1FwLabel[0] = 0; 479 vpd->sli2FwLabel[0] = 0; 480 vpd->sli3FwLabel[0] = 0; 481 vpd->sli4FwLabel[0] = 0; 482 483 EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 484 485 emlxs_mb_get_sli4_params(hba, mbq); 486 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 487 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 488 "Unable to read parameters. Mailbox cmd=%x status=%x", 489 mb->mbxCommand, mb->mbxStatus); 490 491 /* Set param defaults */ 492 emlxs_sli4_set_default_params(hba); 493 494 } else { 495 /* Save parameters */ 496 bcopy((char *)&mb->un.varSLIConfig.payload, 497 (char *)&hba->sli.sli4.param, sizeof (sli_params_t)); 498 499 emlxs_data_dump(port, "SLI_PARMS", 500 (uint32_t *)&hba->sli.sli4.param, 501 sizeof (sli_params_t), 0); 502 } 503 504 /* Reuse mbq from previous mbox */ 505 bzero(mbq, sizeof (MAILBOXQ)); 506 507 emlxs_mb_get_port_name(hba, mbq); 508 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 509 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 510 "Unable to get port names. Mailbox cmd=%x status=%x", 511 mb->mbxCommand, mb->mbxStatus); 512 513 bzero(hba->sli.sli4.port_name, 514 sizeof (hba->sli.sli4.port_name)); 515 } else { 516 /* Save port names */ 517 bcopy((char *)&mb->un.varSLIConfig.payload, 518 (char *)&hba->sli.sli4.port_name, 519 sizeof (hba->sli.sli4.port_name)); 520 } 521 522 /* Reuse mbq from previous mbox */ 523 bzero(mbq, sizeof (MAILBOXQ)); 524 525 emlxs_mb_read_rev(hba, mbq, 0); 526 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 528 "Unable to read rev. Mailbox cmd=%x status=%x", 529 mb->mbxCommand, mb->mbxStatus); 530 531 rval = EIO; 532 goto failed1; 533 534 } 535 536 emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0); 537 if (mb->un.varRdRev4.sliLevel != 4) { 538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 539 "Invalid read rev Version for SLI4: 0x%x", 540 mb->un.varRdRev4.sliLevel); 541 542 rval = EIO; 543 goto failed1; 544 } 545 546 switch (mb->un.varRdRev4.dcbxMode) { 547 case EMLXS_DCBX_MODE_CIN: /* Mapped to nonFIP mode */ 548 hba->flag &= ~FC_FIP_SUPPORTED; 549 break; 550 551 case EMLXS_DCBX_MODE_CEE: /* Mapped to FIP mode */ 552 hba->flag |= FC_FIP_SUPPORTED; 553 break; 554 555 default: 556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 557 "Invalid read rev dcbx mode for SLI4: 0x%x", 558 mb->un.varRdRev4.dcbxMode); 559 560 rval = EIO; 561 goto failed1; 562 } 563 564 /* Set FC/FCoE mode */ 565 if (mb->un.varRdRev4.FCoE) { 566 hba->sli.sli4.flag |= EMLXS_SLI4_FCOE_MODE; 567 } else { 568 hba->sli.sli4.flag &= ~EMLXS_SLI4_FCOE_MODE; 569 } 570 571 /* Save information as VPD data */ 572 vpd->rBit = 1; 573 574 vpd->sli4FwRev = (mb->un.varRdRev4.ULPFwId); 575 bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->sli4FwName, 16); 576 577 vpd->opFwRev = (mb->un.varRdRev4.ULPFwId); 578 bcopy((char *)mb->un.varRdRev4.ULPFwName, vpd->opFwName, 16); 579 580 vpd->postKernRev = (mb->un.varRdRev4.ARMFwId); 581 bcopy((char *)mb->un.varRdRev4.ARMFwName, vpd->postKernName, 16); 582 583 vpd->biuRev = mb->un.varRdRev4.HwRev1; 584 vpd->fcphHigh = mb->un.varRdRev4.fcphHigh; 585 vpd->fcphLow = mb->un.varRdRev4.fcphLow; 586 vpd->feaLevelHigh = mb->un.varRdRev4.feaLevelHigh; 587 vpd->feaLevelLow = mb->un.varRdRev4.feaLevelLow; 588 589 /* Decode FW labels */ 590 if ((hba->model_info.chip & EMLXS_LANCER_CHIPS) != 0) { 591 bcopy(vpd->postKernName, vpd->sli4FwName, 16); 592 } 593 emlxs_decode_label(vpd->sli4FwName, vpd->sli4FwName, 0, 594 sizeof (vpd->sli4FwName)); 595 emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0, 596 sizeof (vpd->opFwName)); 597 emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0, 598 sizeof (vpd->postKernName)); 599 600 if (hba->model_info.chip == EMLXS_BE2_CHIP) { 601 (void) strlcpy(vpd->sli4FwLabel, "be2.ufi", 602 sizeof (vpd->sli4FwLabel)); 603 } else if (hba->model_info.chip == EMLXS_BE3_CHIP) { 604 (void) strlcpy(vpd->sli4FwLabel, "be3.ufi", 605 sizeof (vpd->sli4FwLabel)); 606 } else if (hba->model_info.chip == EMLXS_LANCER_CHIP) { 607 (void) strlcpy(vpd->sli4FwLabel, "xe201.grp", 608 sizeof (vpd->sli4FwLabel)); 609 } else if (hba->model_info.chip == EMLXS_LANCERG6_CHIP) { 610 (void) strlcpy(vpd->sli4FwLabel, "xe501.grp", 611 sizeof (vpd->sli4FwLabel)); 612 } else if (hba->model_info.chip == EMLXS_PRISMG7_CHIP) { 613 (void) strlcpy(vpd->sli4FwLabel, "xe601.grp", 614 sizeof (vpd->sli4FwLabel)); 615 } else { 616 (void) strlcpy(vpd->sli4FwLabel, "sli4.fw", 617 sizeof (vpd->sli4FwLabel)); 618 } 619 620 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 621 "VPD ULP:%08x %s ARM:%08x %s f:%d %d %d %d : dcbx %d", 622 vpd->opFwRev, vpd->opFwName, vpd->postKernRev, vpd->postKernName, 623 vpd->fcphHigh, vpd->fcphLow, vpd->feaLevelHigh, vpd->feaLevelLow, 624 mb->un.varRdRev4.dcbxMode); 625 626 /* No key information is needed for SLI4 products */ 627 628 /* Get adapter VPD information */ 629 vpd->port_index = (uint32_t)-1; 630 631 /* Reuse mbq from previous mbox */ 632 bzero(mbq, sizeof (MAILBOXQ)); 633 634 emlxs_mb_dump_vpd(hba, mbq, 0); 635 vpd_data = hba->sli.sli4.dump_region.virt; 636 637 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 638 MBX_SUCCESS) { 639 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 640 "No VPD found. status=%x", mb->mbxStatus); 641 } else { 642 EMLXS_MSGF(EMLXS_CONTEXT, 643 &emlxs_init_debug_msg, 644 "VPD dumped. rsp_cnt=%d status=%x", 645 mb->un.varDmp4.rsp_cnt, mb->mbxStatus); 646 647 if (mb->un.varDmp4.rsp_cnt) { 648 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 649 0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL); 650 651 #ifdef FMA_SUPPORT 652 if (hba->sli.sli4.dump_region.dma_handle) { 653 if (emlxs_fm_check_dma_handle(hba, 654 hba->sli.sli4.dump_region.dma_handle) 655 != DDI_FM_OK) { 656 EMLXS_MSGF(EMLXS_CONTEXT, 657 &emlxs_invalid_dma_handle_msg, 658 "sli4_online: hdl=%p", 659 hba->sli.sli4.dump_region. 660 dma_handle); 661 rval = EIO; 662 goto failed1; 663 } 664 } 665 #endif /* FMA_SUPPORT */ 666 667 } 668 } 669 670 if (vpd_data[0]) { 671 (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, 672 mb->un.varDmp4.rsp_cnt); 673 674 /* 675 * If there is a VPD part number, and it does not 676 * match the current default HBA model info, 677 * replace the default data with an entry that 678 * does match. 679 * 680 * After emlxs_parse_vpd model holds the VPD value 681 * for V2 and part_num hold the value for PN. These 682 * 2 values are NOT necessarily the same. 683 */ 684 685 rval = 0; 686 if ((vpd->model[0] != 0) && 687 (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 688 689 /* First scan for a V2 match */ 690 691 for (i = 1; i < emlxs_pci_model_count; i++) { 692 if (strcmp(&vpd->model[0], 693 emlxs_pci_model[i].model) == 0) { 694 bcopy(&emlxs_pci_model[i], 695 &hba->model_info, 696 sizeof (emlxs_model_t)); 697 rval = 1; 698 break; 699 } 700 } 701 } 702 703 if (!rval && (vpd->part_num[0] != 0) && 704 (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 705 706 /* Next scan for a PN match */ 707 708 for (i = 1; i < emlxs_pci_model_count; i++) { 709 if (strcmp(&vpd->part_num[0], 710 emlxs_pci_model[i].model) == 0) { 711 bcopy(&emlxs_pci_model[i], 712 &hba->model_info, 713 sizeof (emlxs_model_t)); 714 break; 715 } 716 } 717 } 718 719 /* HP CNA port indices start at 1 instead of 0 */ 720 if (hba->model_info.chip & EMLXS_BE_CHIPS) { 721 ssvid = ddi_get16(hba->pci_acc_handle, 722 (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER)); 723 724 if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) { 725 vpd->port_index--; 726 } 727 } 728 729 /* 730 * Now lets update hba->model_info with the real 731 * VPD data, if any. 732 */ 733 734 /* 735 * Replace the default model description with vpd data 736 */ 737 if (vpd->model_desc[0] != 0) { 738 (void) strncpy(hba->model_info.model_desc, 739 vpd->model_desc, 740 (sizeof (hba->model_info.model_desc)-1)); 741 } 742 743 /* Replace the default model with vpd data */ 744 if (vpd->model[0] != 0) { 745 (void) strncpy(hba->model_info.model, vpd->model, 746 (sizeof (hba->model_info.model)-1)); 747 } 748 749 /* Replace the default program types with vpd data */ 750 if (vpd->prog_types[0] != 0) { 751 emlxs_parse_prog_types(hba, vpd->prog_types); 752 } 753 } 754 755 /* 756 * Since the adapter model may have changed with the vpd data 757 * lets double check if adapter is not supported 758 */ 759 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 760 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 761 "Unsupported adapter found. " 762 "Id:%d Vendor id:0x%x Device id:0x%x SSDID:0x%x " 763 "Model:%s", hba->model_info.id, hba->model_info.vendor_id, 764 hba->model_info.device_id, hba->model_info.ssdid, 765 hba->model_info.model); 766 767 rval = EIO; 768 goto failed1; 769 } 770 771 (void) strncpy(vpd->boot_version, vpd->sli4FwName, 772 (sizeof (vpd->boot_version)-1)); 773 774 /* Get fcode version property */ 775 emlxs_get_fcode_version(hba); 776 777 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 778 "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 779 vpd->opFwRev, vpd->sli1FwRev); 780 781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 782 "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 783 vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 784 785 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 786 "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 787 788 /* 789 * If firmware checking is enabled and the adapter model indicates 790 * a firmware image, then perform firmware version check 791 */ 792 hba->fw_flag = 0; 793 hba->fw_timer = 0; 794 795 if (((fw_check & 0x1) && 796 (hba->model_info.flags & EMLXS_ORACLE_BRANDED) && 797 hba->model_info.fwid) || 798 ((fw_check & 0x2) && hba->model_info.fwid)) { 799 800 /* Find firmware image indicated by adapter model */ 801 fw = NULL; 802 for (i = 0; i < emlxs_fw_count; i++) { 803 if (emlxs_fw_table[i].id == hba->model_info.fwid) { 804 fw = &emlxs_fw_table[i]; 805 break; 806 } 807 } 808 809 /* 810 * If the image was found, then verify current firmware 811 * versions of adapter 812 */ 813 if (fw) { 814 /* Obtain current firmware version info */ 815 if (hba->model_info.chip & EMLXS_BE_CHIPS) { 816 (void) emlxs_be_read_fw_version(hba, &hba_fw); 817 } else { 818 hba_fw.kern = vpd->postKernRev; 819 hba_fw.stub = vpd->opFwRev; 820 hba_fw.sli1 = vpd->sli1FwRev; 821 hba_fw.sli2 = vpd->sli2FwRev; 822 hba_fw.sli3 = vpd->sli3FwRev; 823 hba_fw.sli4 = vpd->sli4FwRev; 824 } 825 826 if (!kern_update && 827 ((fw->kern && (hba_fw.kern != fw->kern)) || 828 (fw->stub && (hba_fw.stub != fw->stub)))) { 829 830 hba->fw_flag |= FW_UPDATE_NEEDED; 831 832 } else if ((fw->kern && (hba_fw.kern != fw->kern)) || 833 (fw->stub && (hba_fw.stub != fw->stub)) || 834 (fw->sli1 && (hba_fw.sli1 != fw->sli1)) || 835 (fw->sli2 && (hba_fw.sli2 != fw->sli2)) || 836 (fw->sli3 && (hba_fw.sli3 != fw->sli3)) || 837 (fw->sli4 && (hba_fw.sli4 != fw->sli4))) { 838 839 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 840 "Firmware update needed. " 841 "Updating. id=%d fw=%d", 842 hba->model_info.id, hba->model_info.fwid); 843 844 #ifdef MODFW_SUPPORT 845 /* 846 * Load the firmware image now 847 * If MODFW_SUPPORT is not defined, the 848 * firmware image will already be defined 849 * in the emlxs_fw_table 850 */ 851 emlxs_fw_load(hba, fw); 852 #endif /* MODFW_SUPPORT */ 853 854 if (fw->image && fw->size) { 855 uint32_t rc; 856 857 rc = emlxs_fw_download(hba, 858 (char *)fw->image, fw->size, 0); 859 if ((rc != FC_SUCCESS) && 860 (rc != EMLXS_REBOOT_REQUIRED)) { 861 EMLXS_MSGF(EMLXS_CONTEXT, 862 &emlxs_init_msg, 863 "Firmware update failed."); 864 hba->fw_flag |= 865 FW_UPDATE_NEEDED; 866 } 867 #ifdef MODFW_SUPPORT 868 /* 869 * Unload the firmware image from 870 * kernel memory 871 */ 872 emlxs_fw_unload(hba, fw); 873 #endif /* MODFW_SUPPORT */ 874 875 fw_check = 0; 876 877 goto reset; 878 } 879 880 hba->fw_flag |= FW_UPDATE_NEEDED; 881 882 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 883 "Firmware image unavailable."); 884 } else { 885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 886 "Firmware update not needed."); 887 } 888 } else { 889 /* 890 * This means either the adapter database is not 891 * correct or a firmware image is missing from the 892 * compile 893 */ 894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 895 "Firmware image unavailable. id=%d fw=%d", 896 hba->model_info.id, hba->model_info.fwid); 897 } 898 } 899 900 /* Reuse mbq from previous mbox */ 901 bzero(mbq, sizeof (MAILBOXQ)); 902 903 emlxs_mb_dump_fcoe(hba, mbq, 0); 904 905 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 906 MBX_SUCCESS) { 907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 908 "No FCOE info found. status=%x", mb->mbxStatus); 909 } else { 910 EMLXS_MSGF(EMLXS_CONTEXT, 911 &emlxs_init_debug_msg, 912 "FCOE info dumped. rsp_cnt=%d status=%x", 913 mb->un.varDmp4.rsp_cnt, mb->mbxStatus); 914 (void) emlxs_parse_fcoe(hba, 915 (uint8_t *)hba->sli.sli4.dump_region.virt, 916 mb->un.varDmp4.rsp_cnt); 917 } 918 919 /* Reuse mbq from previous mbox */ 920 bzero(mbq, sizeof (MAILBOXQ)); 921 922 status = 0; 923 if (port->flag & EMLXS_INI_ENABLED) { 924 status |= SLI4_FEATURE_FCP_INITIATOR; 925 } 926 if (port->flag & EMLXS_TGT_ENABLED) { 927 status |= SLI4_FEATURE_FCP_TARGET; 928 } 929 if (cfg[CFG_NPIV_ENABLE].current) { 930 status |= SLI4_FEATURE_NPIV; 931 } 932 if (cfg[CFG_RQD_MODE].current) { 933 status |= SLI4_FEATURE_RQD; 934 } 935 if (cfg[CFG_PERF_HINT].current) { 936 if (hba->sli.sli4.param.PHON) { 937 status |= SLI4_FEATURE_PERF_HINT; 938 } 939 } 940 941 emlxs_mb_request_features(hba, mbq, status); 942 943 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 945 "Unable to REQUEST_FEATURES. Mailbox cmd=%x status=%x", 946 mb->mbxCommand, mb->mbxStatus); 947 948 rval = EIO; 949 goto failed1; 950 } 951 emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0); 952 953 /* Check to see if we get the features we requested */ 954 if (status != mb->un.varReqFeatures.featuresEnabled) { 955 956 /* Just report descrepencies, don't abort the attach */ 957 958 outptr = (uint8_t *)emlxs_request_feature_xlate( 959 mb->un.varReqFeatures.featuresRequested); 960 (void) strlcpy(buf, (char *)outptr, sizeof (buf)); 961 962 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 963 "REQUEST_FEATURES: wanted:%s got:%s", 964 &buf[0], emlxs_request_feature_xlate( 965 mb->un.varReqFeatures.featuresEnabled)); 966 967 } 968 969 if ((port->flag & EMLXS_INI_ENABLED) && 970 !(mb->un.varReqFeatures.featuresEnabled & 971 SLI4_FEATURE_FCP_INITIATOR)) { 972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 973 "Initiator mode not supported by adapter."); 974 975 rval = EIO; 976 977 #ifdef SFCT_SUPPORT 978 /* Check if we can fall back to just target mode */ 979 if ((hba->pm_state == EMLXS_PM_IN_ATTACH) && 980 (mb->un.varReqFeatures.featuresEnabled & 981 SLI4_FEATURE_FCP_TARGET) && 982 (cfg[CFG_DTM_ENABLE].current == 1) && 983 (cfg[CFG_TARGET_MODE].current == 1)) { 984 985 cfg[CFG_DTM_ENABLE].current = 0; 986 987 EMLXS_MSGF(EMLXS_CONTEXT, 988 &emlxs_init_failed_msg, 989 "Disabling dynamic target mode. " 990 "Enabling target mode only."); 991 992 /* This will trigger the driver to reattach */ 993 rval = EAGAIN; 994 } 995 #endif /* SFCT_SUPPORT */ 996 goto failed1; 997 } 998 999 if ((port->flag & EMLXS_TGT_ENABLED) && 1000 !(mb->un.varReqFeatures.featuresEnabled & 1001 SLI4_FEATURE_FCP_TARGET)) { 1002 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1003 "Target mode not supported by adapter."); 1004 1005 rval = EIO; 1006 1007 #ifdef SFCT_SUPPORT 1008 /* Check if we can fall back to just initiator mode */ 1009 if ((hba->pm_state == EMLXS_PM_IN_ATTACH) && 1010 (mb->un.varReqFeatures.featuresEnabled & 1011 SLI4_FEATURE_FCP_INITIATOR) && 1012 (cfg[CFG_DTM_ENABLE].current == 1) && 1013 (cfg[CFG_TARGET_MODE].current == 0)) { 1014 1015 cfg[CFG_DTM_ENABLE].current = 0; 1016 1017 EMLXS_MSGF(EMLXS_CONTEXT, 1018 &emlxs_init_failed_msg, 1019 "Disabling dynamic target mode. " 1020 "Enabling initiator mode only."); 1021 1022 /* This will trigger the driver to reattach */ 1023 rval = EAGAIN; 1024 } 1025 #endif /* SFCT_SUPPORT */ 1026 goto failed1; 1027 } 1028 1029 if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_NPIV) { 1030 hba->flag |= FC_NPIV_ENABLED; 1031 } 1032 1033 if (mb->un.varReqFeatures.featuresEnabled & SLI4_FEATURE_PERF_HINT) { 1034 hba->sli.sli4.flag |= EMLXS_SLI4_PHON; 1035 if (hba->sli.sli4.param.PHWQ) { 1036 hba->sli.sli4.flag |= EMLXS_SLI4_PHWQ; 1037 } 1038 } 1039 1040 /* Reuse mbq from previous mbox */ 1041 bzero(mbq, sizeof (MAILBOXQ)); 1042 1043 emlxs_mb_read_config(hba, mbq); 1044 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1045 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1046 "Unable to READ_CONFIG. Mailbox cmd=%x status=%x", 1047 mb->mbxCommand, mb->mbxStatus); 1048 1049 rval = EIO; 1050 goto failed1; 1051 } 1052 emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0); 1053 1054 /* Set default extents */ 1055 hba->sli.sli4.XRICount = mb->un.varRdConfig4.XRICount; 1056 hba->sli.sli4.XRIExtCount = 1; 1057 hba->sli.sli4.XRIExtSize = hba->sli.sli4.XRICount; 1058 hba->sli.sli4.XRIBase[0] = mb->un.varRdConfig4.XRIBase; 1059 1060 hba->sli.sli4.RPICount = mb->un.varRdConfig4.RPICount; 1061 hba->sli.sli4.RPIExtCount = 1; 1062 hba->sli.sli4.RPIExtSize = hba->sli.sli4.RPICount; 1063 hba->sli.sli4.RPIBase[0] = mb->un.varRdConfig4.RPIBase; 1064 1065 hba->sli.sli4.VPICount = mb->un.varRdConfig4.VPICount; 1066 hba->sli.sli4.VPIExtCount = 1; 1067 hba->sli.sli4.VPIExtSize = hba->sli.sli4.VPICount; 1068 hba->sli.sli4.VPIBase[0] = mb->un.varRdConfig4.VPIBase; 1069 1070 hba->sli.sli4.VFICount = mb->un.varRdConfig4.VFICount; 1071 hba->sli.sli4.VFIExtCount = 1; 1072 hba->sli.sli4.VFIExtSize = hba->sli.sli4.VFICount; 1073 hba->sli.sli4.VFIBase[0] = mb->un.varRdConfig4.VFIBase; 1074 1075 hba->sli.sli4.FCFICount = mb->un.varRdConfig4.FCFICount; 1076 1077 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1078 "CONFIG: xri:%d rpi:%d vpi:%d vfi:%d fcfi:%d", 1079 hba->sli.sli4.XRICount, 1080 hba->sli.sli4.RPICount, 1081 hba->sli.sli4.VPICount, 1082 hba->sli.sli4.VFICount, 1083 hba->sli.sli4.FCFICount); 1084 1085 if ((hba->sli.sli4.XRICount == 0) || 1086 (hba->sli.sli4.RPICount == 0) || 1087 (hba->sli.sli4.VPICount == 0) || 1088 (hba->sli.sli4.VFICount == 0) || 1089 (hba->sli.sli4.FCFICount == 0)) { 1090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1091 "Invalid extent value(s) - xri:%d rpi:%d vpi:%d " 1092 "vfi:%d fcfi:%d", 1093 hba->sli.sli4.XRICount, 1094 hba->sli.sli4.RPICount, 1095 hba->sli.sli4.VPICount, 1096 hba->sli.sli4.VFICount, 1097 hba->sli.sli4.FCFICount); 1098 1099 rval = EIO; 1100 goto failed1; 1101 } 1102 1103 if (mb->un.varRdConfig4.extents) { 1104 if (emlxs_sli4_init_extents(hba, mbq)) { 1105 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1106 "Unable to initialize extents."); 1107 1108 rval = EIO; 1109 goto failed1; 1110 } 1111 } 1112 1113 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1114 "CONFIG: port_name:%c %c %c %c", 1115 hba->sli.sli4.port_name[0], 1116 hba->sli.sli4.port_name[1], 1117 hba->sli.sli4.port_name[2], 1118 hba->sli.sli4.port_name[3]); 1119 1120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1121 "CONFIG: ldv:%d link_type:%d link_number:%d", 1122 mb->un.varRdConfig4.ldv, 1123 mb->un.varRdConfig4.link_type, 1124 mb->un.varRdConfig4.link_number); 1125 1126 if (mb->un.varRdConfig4.ldv) { 1127 hba->sli.sli4.link_number = mb->un.varRdConfig4.link_number; 1128 } else { 1129 hba->sli.sli4.link_number = (uint32_t)-1; 1130 } 1131 1132 if (hba->sli.sli4.VPICount) { 1133 hba->vpi_max = min(hba->sli.sli4.VPICount, MAX_VPORTS) - 1; 1134 } 1135 1136 /* Set the max node count */ 1137 if (cfg[CFG_NUM_NODES].current > 0) { 1138 hba->max_nodes = 1139 min(cfg[CFG_NUM_NODES].current, 1140 hba->sli.sli4.RPICount); 1141 } else { 1142 hba->max_nodes = hba->sli.sli4.RPICount; 1143 } 1144 1145 /* Set the io throttle */ 1146 hba->io_throttle = hba->sli.sli4.XRICount - IO_THROTTLE_RESERVE; 1147 1148 /* Set max_iotag */ 1149 /* We add 1 in case all XRI's are non-zero */ 1150 hba->max_iotag = hba->sli.sli4.XRICount + 1; 1151 1152 if (cfg[CFG_NUM_IOTAGS].current) { 1153 hba->max_iotag = min(hba->max_iotag, 1154 (uint16_t)cfg[CFG_NUM_IOTAGS].current); 1155 } 1156 1157 /* Set out-of-range iotag base */ 1158 hba->fc_oor_iotag = hba->max_iotag; 1159 1160 /* Save the link speed capabilities */ 1161 vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt; 1162 emlxs_process_link_speed(hba); 1163 1164 /* 1165 * Allocate some memory for buffers 1166 */ 1167 if (emlxs_mem_alloc_buffer(hba) == 0) { 1168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1169 "Unable to allocate memory buffers."); 1170 1171 rval = ENOMEM; 1172 goto failed1; 1173 } 1174 1175 if (emlxs_sli4_resource_alloc(hba)) { 1176 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1177 "Unable to allocate resources."); 1178 1179 rval = ENOMEM; 1180 goto failed2; 1181 } 1182 emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); 1183 emlxs_sli4_zero_queue_stat(hba); 1184 1185 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1186 if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) { 1187 hba->fca_tran->fca_num_npivports = hba->vpi_max; 1188 } 1189 #endif /* >= EMLXS_MODREV5 */ 1190 1191 /* Reuse mbq from previous mbox */ 1192 bzero(mbq, sizeof (MAILBOXQ)); 1193 1194 if (emlxs_sli4_post_sgl_pages(hba, mbq)) { 1195 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1196 "Unable to post sgl pages."); 1197 1198 rval = EIO; 1199 goto failed3; 1200 } 1201 1202 /* Reuse mbq from previous mbox */ 1203 bzero(mbq, sizeof (MAILBOXQ)); 1204 1205 if (emlxs_sli4_post_hdr_tmplates(hba, mbq)) { 1206 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1207 "Unable to post header templates."); 1208 1209 rval = EIO; 1210 goto failed3; 1211 } 1212 1213 /* 1214 * Add our interrupt routine to kernel's interrupt chain & enable it 1215 * If MSI is enabled this will cause Solaris to program the MSI address 1216 * and data registers in PCI config space 1217 */ 1218 if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 1219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1220 "Unable to add interrupt(s)."); 1221 1222 rval = EIO; 1223 goto failed3; 1224 } 1225 1226 /* Reuse mbq from previous mbox */ 1227 bzero(mbq, sizeof (MAILBOXQ)); 1228 1229 /* This MUST be done after EMLXS_INTR_ADD */ 1230 if (emlxs_sli4_create_queues(hba, mbq)) { 1231 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1232 "Unable to create queues."); 1233 1234 rval = EIO; 1235 goto failed3; 1236 } 1237 1238 EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT); 1239 1240 /* Get and save the current firmware version (based on sli_mode) */ 1241 emlxs_decode_firmware_rev(hba, vpd); 1242 1243 1244 EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK); 1245 1246 if (SLI4_FC_MODE) { 1247 /* Reuse mbq from previous mbox */ 1248 bzero(mbq, sizeof (MAILBOXQ)); 1249 1250 emlxs_mb_config_link(hba, mbq); 1251 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1252 MBX_SUCCESS) { 1253 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1254 "Unable to configure link. Mailbox cmd=%x " 1255 "status=%x", 1256 mb->mbxCommand, mb->mbxStatus); 1257 1258 rval = EIO; 1259 goto failed3; 1260 } 1261 } 1262 1263 /* Reuse mbq from previous mbox */ 1264 bzero(mbq, sizeof (MAILBOXQ)); 1265 1266 /* 1267 * We need to get login parameters for NID 1268 */ 1269 (void) emlxs_mb_read_sparam(hba, mbq); 1270 mp = (MATCHMAP *)mbq->bp; 1271 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1272 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1273 "Unable to read parameters. Mailbox cmd=%x status=%x", 1274 mb->mbxCommand, mb->mbxStatus); 1275 1276 rval = EIO; 1277 goto failed3; 1278 } 1279 1280 /* Free the buffer since we were polling */ 1281 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 1282 mp = NULL; 1283 1284 /* If no serial number in VPD data, then use the WWPN */ 1285 if (vpd->serial_num[0] == 0) { 1286 outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 1287 for (i = 0; i < 12; i++) { 1288 status = *outptr++; 1289 j = ((status & 0xf0) >> 4); 1290 if (j <= 9) { 1291 vpd->serial_num[i] = 1292 (char)((uint8_t)'0' + (uint8_t)j); 1293 } else { 1294 vpd->serial_num[i] = 1295 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1296 } 1297 1298 i++; 1299 j = (status & 0xf); 1300 if (j <= 9) { 1301 vpd->serial_num[i] = 1302 (char)((uint8_t)'0' + (uint8_t)j); 1303 } else { 1304 vpd->serial_num[i] = 1305 (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1306 } 1307 } 1308 1309 /* 1310 * Set port number and port index to zero 1311 * The WWN's are unique to each port and therefore port_num 1312 * must equal zero. This effects the hba_fru_details structure 1313 * in fca_bind_port() 1314 */ 1315 vpd->port_num[0] = 0; 1316 vpd->port_index = 0; 1317 1318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1319 "CONFIG: WWPN: port_index=0"); 1320 } 1321 1322 /* Make final attempt to set a port index */ 1323 if (vpd->port_index == (uint32_t)-1) { 1324 dev_info_t *p_dip; 1325 dev_info_t *c_dip; 1326 1327 p_dip = ddi_get_parent(hba->dip); 1328 c_dip = ddi_get_child(p_dip); 1329 1330 vpd->port_index = 0; 1331 while (c_dip && (hba->dip != c_dip)) { 1332 c_dip = ddi_get_next_sibling(c_dip); 1333 1334 if (strcmp(ddi_get_name(c_dip), "ethernet") == 0) { 1335 continue; 1336 } 1337 1338 vpd->port_index++; 1339 } 1340 1341 EMLXS_MSGF(EMLXS_CONTEXT, 1342 &emlxs_init_debug_msg, 1343 "CONFIG: Device tree: port_index=%d", 1344 vpd->port_index); 1345 } 1346 1347 if (vpd->port_num[0] == 0) { 1348 if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) { 1349 (void) snprintf(vpd->port_num, 1350 (sizeof (vpd->port_num)-1), 1351 "%d", vpd->port_index); 1352 } 1353 } 1354 1355 if (vpd->id[0] == 0) { 1356 (void) snprintf(vpd->id, (sizeof (vpd->id)-1), 1357 "%s %d", 1358 hba->model_info.model_desc, vpd->port_index); 1359 1360 } 1361 1362 if (vpd->manufacturer[0] == 0) { 1363 (void) strncpy(vpd->manufacturer, hba->model_info.manufacturer, 1364 (sizeof (vpd->manufacturer)-1)); 1365 } 1366 1367 if (vpd->part_num[0] == 0) { 1368 (void) strncpy(vpd->part_num, hba->model_info.model, 1369 (sizeof (vpd->part_num)-1)); 1370 } 1371 1372 if (vpd->model_desc[0] == 0) { 1373 (void) snprintf(vpd->model_desc, (sizeof (vpd->model_desc)-1), 1374 "%s %d", 1375 hba->model_info.model_desc, vpd->port_index); 1376 } 1377 1378 if (vpd->model[0] == 0) { 1379 (void) strncpy(vpd->model, hba->model_info.model, 1380 (sizeof (vpd->model)-1)); 1381 } 1382 1383 if (vpd->prog_types[0] == 0) { 1384 emlxs_build_prog_types(hba, vpd); 1385 } 1386 1387 /* Create the symbolic names */ 1388 (void) snprintf(hba->snn, (sizeof (hba->snn)-1), 1389 "%s %s FV%s DV%s %s", 1390 hba->model_info.manufacturer, hba->model_info.model, 1391 hba->vpd.fw_version, emlxs_version, 1392 (char *)utsname.nodename); 1393 1394 (void) snprintf(hba->spn, (sizeof (hba->spn)-1), 1395 "%s PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1396 hba->model_info.manufacturer, 1397 hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1398 hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1399 hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1400 1401 1402 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN); 1403 emlxs_sli4_enable_intr(hba); 1404 1405 /* Check persist-linkdown */ 1406 if (cfg[CFG_PERSIST_LINKDOWN].current) { 1407 EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST); 1408 goto done; 1409 } 1410 1411 #ifdef SFCT_SUPPORT 1412 if ((port->mode == MODE_TARGET) && 1413 !(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 1414 goto done; 1415 } 1416 #endif /* SFCT_SUPPORT */ 1417 1418 /* Reuse mbq from previous mbox */ 1419 bzero(mbq, sizeof (MAILBOXQ)); 1420 1421 /* 1422 * Interupts are enabled, start the timeout timers now. 1423 */ 1424 emlxs_timer_start(hba); 1425 1426 /* 1427 * Setup and issue mailbox INITIALIZE LINK command 1428 * At this point, the interrupt will be generated by the HW 1429 */ 1430 emlxs_mb_init_link(hba, mbq, 1431 cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); 1432 1433 rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0); 1434 if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) { 1435 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1436 "Unable to initialize link. " 1437 "Mailbox cmd=%x status=%x", 1438 mb->mbxCommand, mb->mbxStatus); 1439 1440 rval = EIO; 1441 goto failed4; 1442 } 1443 1444 /* Wait for link to come up */ 1445 i = cfg[CFG_LINKUP_DELAY].current; 1446 while (i && (hba->state < FC_LINK_UP)) { 1447 /* Check for hardware error */ 1448 if (hba->state == FC_ERROR) { 1449 EMLXS_MSGF(EMLXS_CONTEXT, 1450 &emlxs_init_failed_msg, 1451 "Adapter error."); 1452 1453 rval = EIO; 1454 goto failed4; 1455 } 1456 1457 BUSYWAIT_MS(1000); 1458 i--; 1459 } 1460 if (i == 0) { 1461 EMLXS_MSGF(EMLXS_CONTEXT, 1462 &emlxs_init_msg, 1463 "Link up timeout"); 1464 } 1465 1466 done: 1467 /* 1468 * The leadville driver will now handle the FLOGI at the driver level 1469 */ 1470 1471 if (mbq) { 1472 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1473 mbq = NULL; 1474 mb = NULL; 1475 } 1476 1477 if (hba->model_info.flags & EMLXS_GPIO_LEDS) 1478 emlxs_sli4_gpio_timer_start(hba); 1479 1480 return (0); 1481 1482 failed4: 1483 emlxs_timer_stop(hba); 1484 1485 failed3: 1486 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1487 1488 if (mp) { 1489 emlxs_mem_put(hba, MEM_BUF, (void *)mp); 1490 mp = NULL; 1491 } 1492 1493 1494 if (hba->intr_flags & EMLXS_MSI_ADDED) { 1495 (void) EMLXS_INTR_REMOVE(hba); 1496 } 1497 1498 emlxs_sli4_resource_free(hba); 1499 1500 failed2: 1501 (void) emlxs_mem_free_buffer(hba); 1502 1503 failed1: 1504 if (mbq) { 1505 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1506 mbq = NULL; 1507 mb = NULL; 1508 } 1509 1510 if (hba->sli.sli4.dump_region.virt) { 1511 mutex_enter(&EMLXS_PORT_LOCK); 1512 (void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region); 1513 mutex_exit(&EMLXS_PORT_LOCK); 1514 } 1515 1516 if (rval == 0) { 1517 rval = EIO; 1518 } 1519 1520 return (rval); 1521 1522 } /* emlxs_sli4_online() */ 1523 1524 1525 static void 1526 emlxs_sli4_offline(emlxs_hba_t *hba, uint32_t reset_requested) 1527 { 1528 /* Reverse emlxs_sli4_online */ 1529 1530 if (hba->model_info.flags & EMLXS_GPIO_LEDS) 1531 emlxs_sli4_gpio_timer_stop(hba); 1532 1533 mutex_enter(&EMLXS_PORT_LOCK); 1534 if (hba->flag & FC_INTERLOCKED) { 1535 mutex_exit(&EMLXS_PORT_LOCK); 1536 goto killed; 1537 } 1538 mutex_exit(&EMLXS_PORT_LOCK); 1539 1540 if (reset_requested) { 1541 (void) emlxs_sli4_hba_reset(hba, 0, 0, 0); 1542 } 1543 1544 /* Shutdown the adapter interface */ 1545 emlxs_sli4_hba_kill(hba); 1546 1547 killed: 1548 1549 /* Free SLI shared memory */ 1550 emlxs_sli4_resource_free(hba); 1551 1552 /* Free driver shared memory */ 1553 (void) emlxs_mem_free_buffer(hba); 1554 1555 /* Free the host dump region buffer */ 1556 mutex_enter(&EMLXS_PORT_LOCK); 1557 (void) emlxs_mem_free(hba, &hba->sli.sli4.dump_region); 1558 mutex_exit(&EMLXS_PORT_LOCK); 1559 1560 } /* emlxs_sli4_offline() */ 1561 1562 static int 1563 emlxs_map_g7_bars(emlxs_hba_t *hba) 1564 { 1565 emlxs_port_t *port = &PPORT; 1566 dev_info_t *dip; 1567 ddi_device_acc_attr_t dev_attr = emlxs_dev_acc_attr; 1568 uint_t num_prop; 1569 pci_regspec_t *prop; 1570 int rnum, type, size, rcount, r; 1571 1572 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0, 1573 "reg", (int **)&prop, &num_prop) != DDI_PROP_SUCCESS) { 1574 return (0); 1575 } 1576 1577 dip = (dev_info_t *)hba->dip; 1578 rcount = num_prop * sizeof (int) / sizeof (pci_regspec_t); 1579 for (r = 0; r < rcount; r++) { 1580 rnum = PCI_REG_REG_G(prop[r].pci_phys_hi); 1581 type = PCI_ADDR_MASK &prop[r].pci_phys_hi; 1582 size = prop[r].pci_size_low; 1583 EMLXS_MSGF(EMLXS_CONTEXT, 1584 &emlxs_init_debug_msg, 1585 "PCI_BAR%x regaddr=%x type=%x size=%x", 1586 r, rnum, PCI_REG_ADDR_G(type), size); 1587 if (type < PCI_ADDR_MEM32) { 1588 /* config or IO reg address */ 1589 continue; 1590 } 1591 /* MEM reg address */ 1592 caddr_t addr; 1593 ddi_acc_handle_t handle; 1594 int status; 1595 1596 status = ddi_regs_map_setup(dip, r, 1597 (caddr_t *)&addr, 0, 0, &dev_attr, 1598 &handle); 1599 if (status != DDI_SUCCESS) { 1600 EMLXS_MSGF(EMLXS_CONTEXT, 1601 &emlxs_attach_failed_msg, 1602 "ddi_regs_map_setup BAR%d failed." 1603 " status=%x", 1604 r, status); 1605 ddi_prop_free((void *)prop); 1606 return (0); 1607 } 1608 switch (r-1) { 1609 case 0: 1610 if (hba->sli.sli4.bar0_acc_handle == 0) { 1611 hba->sli.sli4.bar0_addr = addr; 1612 hba->sli.sli4.bar0_acc_handle = 1613 handle; 1614 } 1615 break; 1616 case 1: 1617 if (hba->sli.sli4.bar1_acc_handle == 0) { 1618 hba->sli.sli4.bar1_addr = addr; 1619 hba->sli.sli4.bar1_acc_handle = 1620 handle; 1621 } 1622 break; 1623 case 2: 1624 if (hba->sli.sli4.bar2_acc_handle == 0) { 1625 hba->sli.sli4.bar2_addr = addr; 1626 hba->sli.sli4.bar2_acc_handle = 1627 handle; 1628 } 1629 break; 1630 } 1631 } 1632 ddi_prop_free((void *)prop); 1633 return (num_prop > 0); 1634 } 1635 1636 /*ARGSUSED*/ 1637 static int 1638 emlxs_sli4_map_hdw(emlxs_hba_t *hba) 1639 { 1640 emlxs_port_t *port = &PPORT; 1641 dev_info_t *dip; 1642 ddi_device_acc_attr_t dev_attr; 1643 int status; 1644 1645 dip = (dev_info_t *)hba->dip; 1646 dev_attr = emlxs_dev_acc_attr; 1647 1648 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 1649 case SLI_INTF_IF_TYPE_0: 1650 1651 /* Map in Hardware BAR pages that will be used for */ 1652 /* communication with HBA. */ 1653 if (hba->sli.sli4.bar1_acc_handle == 0) { 1654 status = ddi_regs_map_setup(dip, PCI_BAR1_RINDEX, 1655 (caddr_t *)&hba->sli.sli4.bar1_addr, 1656 0, 0, &dev_attr, &hba->sli.sli4.bar1_acc_handle); 1657 if (status != DDI_SUCCESS) { 1658 EMLXS_MSGF(EMLXS_CONTEXT, 1659 &emlxs_attach_failed_msg, 1660 "(PCI) ddi_regs_map_setup BAR1 failed. " 1661 "stat=%d mem=%p attr=%p hdl=%p", 1662 status, &hba->sli.sli4.bar1_addr, &dev_attr, 1663 &hba->sli.sli4.bar1_acc_handle); 1664 goto failed; 1665 } 1666 } 1667 1668 if (hba->sli.sli4.bar2_acc_handle == 0) { 1669 status = ddi_regs_map_setup(dip, PCI_BAR2_RINDEX, 1670 (caddr_t *)&hba->sli.sli4.bar2_addr, 1671 0, 0, &dev_attr, &hba->sli.sli4.bar2_acc_handle); 1672 if (status != DDI_SUCCESS) { 1673 EMLXS_MSGF(EMLXS_CONTEXT, 1674 &emlxs_attach_failed_msg, 1675 "ddi_regs_map_setup BAR2 failed. status=%x", 1676 status); 1677 goto failed; 1678 } 1679 } 1680 1681 /* offset from beginning of register space */ 1682 hba->sli.sli4.MPUEPSemaphore_reg_addr = 1683 (uint32_t *)(hba->sli.sli4.bar1_addr + 1684 CSR_MPU_EP_SEMAPHORE_OFFSET); 1685 hba->sli.sli4.MBDB_reg_addr = 1686 (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MB_DB_OFFSET); 1687 hba->sli.sli4.CQDB_reg_addr = 1688 (uint32_t *)(hba->sli.sli4.bar2_addr + PD_CQ_DB_OFFSET); 1689 hba->sli.sli4.MQDB_reg_addr = 1690 (uint32_t *)(hba->sli.sli4.bar2_addr + PD_MQ_DB_OFFSET); 1691 hba->sli.sli4.WQDB_reg_addr = 1692 (uint32_t *)(hba->sli.sli4.bar2_addr + PD_WQ_DB_OFFSET); 1693 hba->sli.sli4.RQDB_reg_addr = 1694 (uint32_t *)(hba->sli.sli4.bar2_addr + PD_RQ_DB_OFFSET); 1695 1696 hba->sli.sli4.STATUS_reg_addr = 0; 1697 hba->sli.sli4.CNTL_reg_addr = 0; 1698 1699 hba->sli.sli4.ERR1_reg_addr = 1700 (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_LO_OFFSET); 1701 hba->sli.sli4.ERR2_reg_addr = 1702 (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET); 1703 1704 hba->sli.sli4.PHYSDEV_reg_addr = 0; 1705 break; 1706 1707 case SLI_INTF_IF_TYPE_2: /* Lancer FC */ 1708 1709 /* Map in Hardware BAR pages that will be used for */ 1710 /* communication with HBA. */ 1711 if (hba->sli.sli4.bar0_acc_handle == 0) { 1712 status = ddi_regs_map_setup(dip, PCI_BAR0_RINDEX, 1713 (caddr_t *)&hba->sli.sli4.bar0_addr, 1714 0, 0, &dev_attr, &hba->sli.sli4.bar0_acc_handle); 1715 if (status != DDI_SUCCESS) { 1716 EMLXS_MSGF(EMLXS_CONTEXT, 1717 &emlxs_attach_failed_msg, 1718 "(PCI) ddi_regs_map_setup BAR0 failed. " 1719 "stat=%d mem=%p attr=%p hdl=%p", 1720 status, &hba->sli.sli4.bar0_addr, &dev_attr, 1721 &hba->sli.sli4.bar0_acc_handle); 1722 goto failed; 1723 } 1724 } 1725 1726 /* offset from beginning of register space */ 1727 hba->sli.sli4.MPUEPSemaphore_reg_addr = 1728 (uint32_t *)(hba->sli.sli4.bar0_addr + 1729 SLIPORT_SEMAPHORE_OFFSET); 1730 hba->sli.sli4.MBDB_reg_addr = 1731 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MB_DB_OFFSET); 1732 hba->sli.sli4.CQDB_reg_addr = 1733 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_CQ_DB_OFFSET); 1734 hba->sli.sli4.MQDB_reg_addr = 1735 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MQ_DB_OFFSET); 1736 hba->sli.sli4.WQDB_reg_addr = 1737 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_WQ_DB_OFFSET); 1738 hba->sli.sli4.RQDB_reg_addr = 1739 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_RQ_DB_OFFSET); 1740 1741 hba->sli.sli4.STATUS_reg_addr = 1742 (uint32_t *)(hba->sli.sli4.bar0_addr + 1743 SLIPORT_STATUS_OFFSET); 1744 hba->sli.sli4.CNTL_reg_addr = 1745 (uint32_t *)(hba->sli.sli4.bar0_addr + 1746 SLIPORT_CONTROL_OFFSET); 1747 hba->sli.sli4.ERR1_reg_addr = 1748 (uint32_t *)(hba->sli.sli4.bar0_addr + 1749 SLIPORT_ERROR1_OFFSET); 1750 hba->sli.sli4.ERR2_reg_addr = 1751 (uint32_t *)(hba->sli.sli4.bar0_addr + 1752 SLIPORT_ERROR2_OFFSET); 1753 hba->sli.sli4.PHYSDEV_reg_addr = 1754 (uint32_t *)(hba->sli.sli4.bar0_addr + 1755 PHYSDEV_CONTROL_OFFSET); 1756 1757 break; 1758 case SLI_INTF_IF_TYPE_6: 1759 /* Map in Hardware BAR pages that will be used for */ 1760 /* communication with HBA. */ 1761 if (!emlxs_map_g7_bars(hba)) 1762 goto failed; 1763 /* offset from beginning of register space */ 1764 hba->sli.sli4.MPUEPSemaphore_reg_addr = 1765 (uint32_t *)(hba->sli.sli4.bar0_addr + 1766 SLIPORT_SEMAPHORE_OFFSET); 1767 hba->sli.sli4.MBDB_reg_addr = 1768 (uint32_t *)(hba->sli.sli4.bar0_addr + PD_MB_DB_OFFSET); 1769 hba->sli.sli4.EQDB_reg_addr = 1770 (uint32_t *)(hba->sli.sli4.bar1_addr + PD_IF6_EQ_DB_OFFSET); 1771 hba->sli.sli4.CQDB_reg_addr = 1772 (uint32_t *)(hba->sli.sli4.bar1_addr + PD_IF6_CQ_DB_OFFSET); 1773 hba->sli.sli4.MQDB_reg_addr = 1774 (uint32_t *)(hba->sli.sli4.bar1_addr + PD_IF6_MQ_DB_OFFSET); 1775 hba->sli.sli4.WQDB_reg_addr = 1776 (uint32_t *)(hba->sli.sli4.bar1_addr + PD_IF6_WQ_DB_OFFSET); 1777 hba->sli.sli4.RQDB_reg_addr = 1778 (uint32_t *)(hba->sli.sli4.bar1_addr + PD_IF6_RQ_DB_OFFSET); 1779 1780 hba->sli.sli4.STATUS_reg_addr = 1781 (uint32_t *)(hba->sli.sli4.bar0_addr + 1782 SLIPORT_STATUS_OFFSET); 1783 hba->sli.sli4.CNTL_reg_addr = 1784 (uint32_t *)(hba->sli.sli4.bar0_addr + 1785 SLIPORT_CONTROL_OFFSET); 1786 hba->sli.sli4.ERR1_reg_addr = 1787 (uint32_t *)(hba->sli.sli4.bar0_addr + 1788 SLIPORT_ERROR1_OFFSET); 1789 hba->sli.sli4.ERR2_reg_addr = 1790 (uint32_t *)(hba->sli.sli4.bar0_addr + 1791 SLIPORT_ERROR2_OFFSET); 1792 hba->sli.sli4.PHYSDEV_reg_addr = 1793 (uint32_t *)(hba->sli.sli4.bar0_addr + 1794 PHYSDEV_CONTROL_OFFSET); 1795 1796 break; 1797 case SLI_INTF_IF_TYPE_1: 1798 case SLI_INTF_IF_TYPE_3: 1799 default: 1800 EMLXS_MSGF(EMLXS_CONTEXT, 1801 &emlxs_attach_failed_msg, 1802 "Map hdw: Unsupported if_type %08x", 1803 (hba->sli_intf & SLI_INTF_IF_TYPE_MASK)); 1804 1805 goto failed; 1806 } 1807 1808 if (hba->sli.sli4.bootstrapmb.virt == 0) { 1809 MBUF_INFO *buf_info; 1810 MBUF_INFO bufinfo; 1811 1812 buf_info = &bufinfo; 1813 1814 bzero(buf_info, sizeof (MBUF_INFO)); 1815 buf_info->size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE; 1816 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 1817 buf_info->align = ddi_ptob(dip, 1L); 1818 1819 (void) emlxs_mem_alloc(hba, buf_info); 1820 1821 if (buf_info->virt == NULL) { 1822 goto failed; 1823 } 1824 1825 hba->sli.sli4.bootstrapmb.virt = buf_info->virt; 1826 hba->sli.sli4.bootstrapmb.phys = buf_info->phys; 1827 hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE + 1828 MBOX_EXTENSION_SIZE; 1829 hba->sli.sli4.bootstrapmb.data_handle = buf_info->data_handle; 1830 hba->sli.sli4.bootstrapmb.dma_handle = buf_info->dma_handle; 1831 bzero((char *)hba->sli.sli4.bootstrapmb.virt, 1832 EMLXS_BOOTSTRAP_MB_SIZE); 1833 } 1834 1835 hba->chan_count = MAX_CHANNEL; 1836 1837 return (0); 1838 1839 failed: 1840 1841 emlxs_sli4_unmap_hdw(hba); 1842 return (ENOMEM); 1843 1844 1845 } /* emlxs_sli4_map_hdw() */ 1846 1847 1848 /*ARGSUSED*/ 1849 static void 1850 emlxs_sli4_unmap_hdw(emlxs_hba_t *hba) 1851 { 1852 MBUF_INFO bufinfo; 1853 MBUF_INFO *buf_info = &bufinfo; 1854 1855 1856 if (hba->sli.sli4.bar0_acc_handle) { 1857 ddi_regs_map_free(&hba->sli.sli4.bar0_acc_handle); 1858 hba->sli.sli4.bar0_acc_handle = 0; 1859 } 1860 1861 if (hba->sli.sli4.bar1_acc_handle) { 1862 ddi_regs_map_free(&hba->sli.sli4.bar1_acc_handle); 1863 hba->sli.sli4.bar1_acc_handle = 0; 1864 } 1865 1866 if (hba->sli.sli4.bar2_acc_handle) { 1867 ddi_regs_map_free(&hba->sli.sli4.bar2_acc_handle); 1868 hba->sli.sli4.bar2_acc_handle = 0; 1869 } 1870 1871 if (hba->sli.sli4.bootstrapmb.virt) { 1872 bzero(buf_info, sizeof (MBUF_INFO)); 1873 1874 if (hba->sli.sli4.bootstrapmb.phys) { 1875 buf_info->phys = hba->sli.sli4.bootstrapmb.phys; 1876 buf_info->data_handle = 1877 hba->sli.sli4.bootstrapmb.data_handle; 1878 buf_info->dma_handle = 1879 hba->sli.sli4.bootstrapmb.dma_handle; 1880 buf_info->flags = FC_MBUF_DMA; 1881 } 1882 1883 buf_info->virt = hba->sli.sli4.bootstrapmb.virt; 1884 buf_info->size = hba->sli.sli4.bootstrapmb.size; 1885 emlxs_mem_free(hba, buf_info); 1886 1887 hba->sli.sli4.bootstrapmb.virt = NULL; 1888 } 1889 1890 return; 1891 1892 } /* emlxs_sli4_unmap_hdw() */ 1893 1894 1895 static int 1896 emlxs_check_hdw_ready(emlxs_hba_t *hba) 1897 { 1898 emlxs_port_t *port = &PPORT; 1899 uint32_t status; 1900 uint32_t i = 0; 1901 uint32_t err1; 1902 uint32_t err2; 1903 1904 /* Wait for reset completion */ 1905 while (i < 30) { 1906 1907 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 1908 case SLI_INTF_IF_TYPE_0: 1909 status = emlxs_sli4_read_sema(hba); 1910 1911 /* Check to see if any errors occurred during init */ 1912 if (status & ARM_POST_FATAL) { 1913 EMLXS_MSGF(EMLXS_CONTEXT, 1914 &emlxs_reset_failed_msg, 1915 "SEMA Error: status=%x", status); 1916 1917 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1918 1919 return (1); 1920 } 1921 1922 if ((status & ARM_UNRECOVERABLE_ERROR) == 1923 ARM_UNRECOVERABLE_ERROR) { 1924 EMLXS_MSGF(EMLXS_CONTEXT, 1925 &emlxs_reset_failed_msg, 1926 "Unrecoverable Error: status=%x", status); 1927 1928 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1929 1930 return (1); 1931 } 1932 1933 if ((status & ARM_POST_MASK) == ARM_POST_READY) { 1934 /* ARM Ready !! */ 1935 EMLXS_MSGF(EMLXS_CONTEXT, 1936 &emlxs_sli_detail_msg, 1937 "ARM Ready: status=%x", status); 1938 1939 return (0); 1940 } 1941 break; 1942 1943 case SLI_INTF_IF_TYPE_2: 1944 case SLI_INTF_IF_TYPE_6: 1945 status = emlxs_sli4_read_status(hba); 1946 1947 if (status & SLI_STATUS_READY) { 1948 if (!(status & SLI_STATUS_ERROR)) { 1949 /* ARM Ready !! */ 1950 EMLXS_MSGF(EMLXS_CONTEXT, 1951 &emlxs_sli_detail_msg, 1952 "ARM Ready: status=%x", status); 1953 1954 return (0); 1955 } 1956 1957 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 1958 hba->sli.sli4.ERR1_reg_addr); 1959 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 1960 hba->sli.sli4.ERR2_reg_addr); 1961 1962 if (status & SLI_STATUS_RESET_NEEDED) { 1963 EMLXS_MSGF(EMLXS_CONTEXT, 1964 &emlxs_sli_detail_msg, 1965 "ARM Ready (Reset Needed): " 1966 "status=%x err1=%x " 1967 "err2=%x", 1968 status, err1, err2); 1969 1970 return (1); 1971 } 1972 1973 EMLXS_MSGF(EMLXS_CONTEXT, 1974 &emlxs_reset_failed_msg, 1975 "Unrecoverable Error: status=%x err1=%x " 1976 "err2=%x", 1977 status, err1, err2); 1978 1979 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1980 1981 return (2); 1982 } 1983 1984 break; 1985 1986 default: 1987 EMLXS_STATE_CHANGE(hba, FC_ERROR); 1988 1989 return (3); 1990 } 1991 1992 BUSYWAIT_MS(1000); 1993 i++; 1994 } 1995 1996 /* Timeout occurred */ 1997 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 1998 case SLI_INTF_IF_TYPE_0: 1999 err1 = ddi_get32(hba->pci_acc_handle, 2000 hba->sli.sli4.ERR1_reg_addr); 2001 err2 = ddi_get32(hba->pci_acc_handle, 2002 hba->sli.sli4.ERR2_reg_addr); 2003 break; 2004 2005 default: 2006 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2007 hba->sli.sli4.ERR1_reg_addr); 2008 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2009 hba->sli.sli4.ERR2_reg_addr); 2010 break; 2011 } 2012 2013 if (status & SLI_STATUS_ERROR) { 2014 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2015 "Ready Timeout: Port Error: status=%x err1=%x err2=%x", 2016 status, err1, err2); 2017 } else { 2018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2019 "Ready Timeout: status=%x err1=%x err2=%x", 2020 status, err1, err2); 2021 } 2022 2023 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2024 2025 return (3); 2026 2027 } /* emlxs_check_hdw_ready() */ 2028 2029 2030 static uint32_t 2031 emlxs_sli4_read_status(emlxs_hba_t *hba) 2032 { 2033 #ifdef FMA_SUPPORT 2034 emlxs_port_t *port = &PPORT; 2035 #endif /* FMA_SUPPORT */ 2036 uint32_t status; 2037 2038 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2039 case SLI_INTF_IF_TYPE_2: 2040 case SLI_INTF_IF_TYPE_6: 2041 status = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2042 hba->sli.sli4.STATUS_reg_addr); 2043 #ifdef FMA_SUPPORT 2044 /* Access handle validation */ 2045 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle); 2046 #endif /* FMA_SUPPORT */ 2047 break; 2048 default: 2049 status = 0; 2050 break; 2051 } 2052 2053 return (status); 2054 2055 } /* emlxs_sli4_read_status() */ 2056 2057 2058 static uint32_t 2059 emlxs_sli4_read_sema(emlxs_hba_t *hba) 2060 { 2061 #ifdef FMA_SUPPORT 2062 emlxs_port_t *port = &PPORT; 2063 #endif /* FMA_SUPPORT */ 2064 uint32_t status; 2065 2066 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2067 case SLI_INTF_IF_TYPE_0: 2068 status = ddi_get32(hba->sli.sli4.bar1_acc_handle, 2069 hba->sli.sli4.MPUEPSemaphore_reg_addr); 2070 #ifdef FMA_SUPPORT 2071 /* Access handle validation */ 2072 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar1_acc_handle); 2073 #endif /* FMA_SUPPORT */ 2074 break; 2075 2076 case SLI_INTF_IF_TYPE_2: 2077 case SLI_INTF_IF_TYPE_6: 2078 status = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2079 hba->sli.sli4.MPUEPSemaphore_reg_addr); 2080 #ifdef FMA_SUPPORT 2081 /* Access handle validation */ 2082 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle); 2083 #endif /* FMA_SUPPORT */ 2084 break; 2085 default: 2086 status = 0; 2087 break; 2088 } 2089 2090 return (status); 2091 2092 } /* emlxs_sli4_read_sema() */ 2093 2094 2095 static uint32_t 2096 emlxs_sli4_read_mbdb(emlxs_hba_t *hba) 2097 { 2098 #ifdef FMA_SUPPORT 2099 emlxs_port_t *port = &PPORT; 2100 #endif /* FMA_SUPPORT */ 2101 uint32_t status; 2102 2103 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2104 case SLI_INTF_IF_TYPE_0: 2105 status = ddi_get32(hba->sli.sli4.bar2_acc_handle, 2106 hba->sli.sli4.MBDB_reg_addr); 2107 2108 #ifdef FMA_SUPPORT 2109 /* Access handle validation */ 2110 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar2_acc_handle); 2111 #endif /* FMA_SUPPORT */ 2112 break; 2113 2114 case SLI_INTF_IF_TYPE_2: 2115 case SLI_INTF_IF_TYPE_6: 2116 status = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2117 hba->sli.sli4.MBDB_reg_addr); 2118 #ifdef FMA_SUPPORT 2119 /* Access handle validation */ 2120 EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli4.bar0_acc_handle); 2121 #endif /* FMA_SUPPORT */ 2122 break; 2123 default: 2124 status = 0; 2125 break; 2126 } 2127 2128 return (status); 2129 2130 } /* emlxs_sli4_read_mbdb() */ 2131 2132 2133 static void 2134 emlxs_sli4_write_mbdb(emlxs_hba_t *hba, uint64_t phys, boolean_t high) 2135 { 2136 uint32_t db; 2137 uint_t shift; 2138 2139 /* 2140 * The bootstrap mailbox is posted as 2 x 30 bit values. 2141 * It is required to be 16 bit aligned, and the 2 low order 2142 * bits are used as flags. 2143 */ 2144 shift = high ? 32 : 2; 2145 2146 db = (uint32_t)(phys >> shift) & BMBX_ADDR; 2147 2148 if (high) 2149 db |= BMBX_ADDR_HI; 2150 2151 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2152 case SLI_INTF_IF_TYPE_0: 2153 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2154 hba->sli.sli4.MBDB_reg_addr, db); 2155 break; 2156 2157 case SLI_INTF_IF_TYPE_2: 2158 case SLI_INTF_IF_TYPE_6: 2159 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2160 hba->sli.sli4.MBDB_reg_addr, db); 2161 break; 2162 } 2163 2164 } /* emlxs_sli4_write_mbdb() */ 2165 2166 2167 static void 2168 emlxs_sli4_write_eqdb(emlxs_hba_t *hba, uint16_t qid, uint32_t count, 2169 boolean_t arm) 2170 { 2171 emlxs_eqdb_u db; 2172 db.word = 0; 2173 2174 /* 2175 * Add the qid to the doorbell. It is split into a low and 2176 * high component. 2177 */ 2178 2179 if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_6) { 2180 db.db6.Qid = qid; 2181 db.db6.NumPopped = count; 2182 db.db6.Rearm = arm; 2183 } else { 2184 /* Initialize with the low bits */ 2185 db.db2.Qid = qid & EQ_DB_ID_LO_MASK; 2186 2187 /* Add the high bits */ 2188 db.db2.Qid_hi = (qid >> EQ_ID_LO_BITS) & 0x1f; 2189 2190 /* 2191 * Include the number of entries to be popped. 2192 */ 2193 db.db2.NumPopped = count; 2194 2195 /* The doorbell is for an event queue */ 2196 db.db2.Event = B_TRUE; 2197 2198 /* Arm if asked to do so */ 2199 if (arm) 2200 /* Clear only on not AutoValid EqAV */ 2201 db.db2.Clear = B_TRUE; 2202 db.db2.Rearm = arm; 2203 } 2204 2205 #ifdef DEBUG_FASTPATH 2206 EMLXS_MSGF(&hba->port[0], _FILENO_, __LINE__, &emlxs_sli_detail_msg, 2207 "EQE: CLEAR db=%08x pops=%d", db, count); 2208 #endif /* DEBUG_FASTPATH */ 2209 2210 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2211 case SLI_INTF_IF_TYPE_0: 2212 /* The CQDB_reg_addr is also use for EQs */ 2213 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2214 hba->sli.sli4.CQDB_reg_addr, db.word); 2215 break; 2216 2217 case SLI_INTF_IF_TYPE_2: 2218 /* The CQDB_reg_addr is also use for EQs */ 2219 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2220 hba->sli.sli4.CQDB_reg_addr, db.word); 2221 break; 2222 2223 case SLI_INTF_IF_TYPE_6: 2224 ddi_put32(hba->sli.sli4.bar1_acc_handle, 2225 hba->sli.sli4.EQDB_reg_addr, db.word); 2226 break; 2227 2228 } 2229 } /* emlxs_sli4_write_eqdb() */ 2230 2231 static void 2232 emlxs_sli4_write_cqdb(emlxs_hba_t *hba, uint16_t qid, uint32_t count, 2233 boolean_t arm) 2234 { 2235 emlxs_cqdb_u db; 2236 db.word = 0; 2237 2238 /* 2239 * Add the qid to the doorbell. It is split into a low and 2240 * high component. 2241 */ 2242 2243 if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_6) { 2244 db.db6.Qid = qid; 2245 db.db6.NumPopped = count; 2246 db.db6.Rearm = arm; 2247 } else { 2248 /* Initialize with the low bits */ 2249 db.db2.Qid = qid & CQ_DB_ID_LO_MASK; 2250 2251 /* Add the high bits */ 2252 db.db2.Qid_hi = (qid >> CQ_ID_LO_BITS) & 0x1f; 2253 2254 /* 2255 * Include the number of entries to be popped. 2256 */ 2257 db.db2.NumPopped = count; 2258 2259 /* Arm if asked to do so */ 2260 db.db2.Rearm = arm; 2261 } 2262 #ifdef DEBUG_FASTPATH 2263 EMLXS_MSGF(&hba->port[0], _FILENO_, __LINE__, &emlxs_sli_detail_msg, 2264 "CQE: db=%08x: pops=%d", db, count); 2265 #endif /* DEBUG_FASTPATH */ 2266 2267 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2268 case SLI_INTF_IF_TYPE_0: 2269 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2270 hba->sli.sli4.CQDB_reg_addr, db.word); 2271 break; 2272 2273 case SLI_INTF_IF_TYPE_2: 2274 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2275 hba->sli.sli4.CQDB_reg_addr, db.word); 2276 break; 2277 2278 case SLI_INTF_IF_TYPE_6: 2279 ddi_put32(hba->sli.sli4.bar1_acc_handle, 2280 hba->sli.sli4.CQDB_reg_addr, db.word); 2281 break; 2282 } 2283 } /* emlxs_sli4_write_cqdb() */ 2284 2285 2286 static void 2287 emlxs_sli4_write_rqdb(emlxs_hba_t *hba, uint16_t qid, uint_t count) 2288 { 2289 emlxs_rqdbu_t rqdb; 2290 2291 rqdb.word = 0; 2292 rqdb.db.Qid = qid; 2293 rqdb.db.NumPosted = count; 2294 2295 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2296 case SLI_INTF_IF_TYPE_0: 2297 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2298 hba->sli.sli4.RQDB_reg_addr, rqdb.word); 2299 break; 2300 2301 case SLI_INTF_IF_TYPE_2: 2302 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2303 hba->sli.sli4.RQDB_reg_addr, rqdb.word); 2304 break; 2305 2306 case SLI_INTF_IF_TYPE_6: 2307 ddi_put32(hba->sli.sli4.bar1_acc_handle, 2308 hba->sli.sli4.RQDB_reg_addr, rqdb.word); 2309 break; 2310 2311 } 2312 2313 } /* emlxs_sli4_write_rqdb() */ 2314 2315 2316 static void 2317 emlxs_sli4_write_mqdb(emlxs_hba_t *hba, uint16_t qid, uint_t count) 2318 { 2319 uint32_t db; 2320 2321 db = qid; 2322 db |= (count << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK; 2323 2324 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2325 case SLI_INTF_IF_TYPE_0: 2326 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2327 hba->sli.sli4.MQDB_reg_addr, db); 2328 break; 2329 2330 case SLI_INTF_IF_TYPE_2: 2331 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2332 hba->sli.sli4.MQDB_reg_addr, db); 2333 break; 2334 case SLI_INTF_IF_TYPE_6: 2335 ddi_put32(hba->sli.sli4.bar1_acc_handle, 2336 hba->sli.sli4.MQDB_reg_addr, db); 2337 break; 2338 } 2339 2340 } /* emlxs_sli4_write_mqdb() */ 2341 2342 2343 static void 2344 emlxs_sli4_write_wqdb(emlxs_hba_t *hba, uint16_t qid, uint_t posted, 2345 uint_t index) 2346 { 2347 uint32_t db; 2348 2349 db = qid; 2350 db |= (posted << WQ_DB_POST_SHIFT) & WQ_DB_POST_MASK; 2351 2352 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2353 case SLI_INTF_IF_TYPE_0: 2354 db |= (index << WQ_DB_IDX_SHIFT) & WQ_DB_IDX_MASK; 2355 ddi_put32(hba->sli.sli4.bar2_acc_handle, 2356 hba->sli.sli4.WQDB_reg_addr, db); 2357 break; 2358 2359 case SLI_INTF_IF_TYPE_2: 2360 db |= (index << WQ_DB_IDX_SHIFT) & WQ_DB_IDX_MASK; 2361 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2362 hba->sli.sli4.WQDB_reg_addr, db); 2363 break; 2364 2365 case SLI_INTF_IF_TYPE_6: 2366 ddi_put32(hba->sli.sli4.bar1_acc_handle, 2367 hba->sli.sli4.WQDB_reg_addr, db); 2368 break; 2369 2370 } 2371 2372 #ifdef DEBUG_FASTPATH 2373 EMLXS_MSGF(&hba->port[0], _FILENO_, __LINE__, &emlxs_sli_detail_msg, 2374 "WQ RING: %08x", db); 2375 #endif /* DEBUG_FASTPATH */ 2376 } /* emlxs_sli4_write_wqdb() */ 2377 2378 2379 static uint32_t 2380 emlxs_check_bootstrap_ready(emlxs_hba_t *hba, uint32_t tmo) 2381 { 2382 emlxs_port_t *port = &PPORT; 2383 uint32_t status = 0; 2384 uint32_t err1; 2385 uint32_t err2; 2386 2387 /* Wait for reset completion, tmo is in 10ms ticks */ 2388 while (tmo) { 2389 status = emlxs_sli4_read_mbdb(hba); 2390 2391 /* Check to see if any errors occurred during init */ 2392 if (status & BMBX_READY) { 2393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2394 "BMBX Ready: status=0x%x", status); 2395 2396 return (tmo); 2397 } 2398 2399 BUSYWAIT_MS(10); 2400 tmo--; 2401 } 2402 2403 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2404 case SLI_INTF_IF_TYPE_0: 2405 err1 = ddi_get32(hba->pci_acc_handle, 2406 hba->sli.sli4.ERR1_reg_addr); 2407 err2 = ddi_get32(hba->pci_acc_handle, 2408 hba->sli.sli4.ERR2_reg_addr); 2409 break; 2410 2411 default: /* IF_TYPE_2 and IF_TYPE_6 */ 2412 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2413 hba->sli.sli4.ERR1_reg_addr); 2414 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2415 hba->sli.sli4.ERR2_reg_addr); 2416 break; 2417 } 2418 2419 /* Timeout occurred */ 2420 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2421 "Timeout waiting for BMailbox: status=%x err1=%x err2=%x", 2422 status, err1, err2); 2423 2424 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2425 2426 return (0); 2427 2428 } /* emlxs_check_bootstrap_ready() */ 2429 2430 2431 static uint32_t 2432 emlxs_issue_bootstrap_mb(emlxs_hba_t *hba, uint32_t tmo) 2433 { 2434 emlxs_port_t *port = &PPORT; 2435 uint32_t *iptr; 2436 2437 /* 2438 * This routine assumes the bootstrap mbox is loaded 2439 * with the mailbox command to be executed. 2440 * 2441 * First, load the high 30 bits of bootstrap mailbox 2442 */ 2443 emlxs_sli4_write_mbdb(hba, hba->sli.sli4.bootstrapmb.phys, B_TRUE); 2444 2445 tmo = emlxs_check_bootstrap_ready(hba, tmo); 2446 if (tmo == 0) { 2447 return (0); 2448 } 2449 2450 /* Load the low 30 bits of bootstrap mailbox */ 2451 emlxs_sli4_write_mbdb(hba, hba->sli.sli4.bootstrapmb.phys, B_FALSE); 2452 2453 tmo = emlxs_check_bootstrap_ready(hba, tmo); 2454 if (tmo == 0) { 2455 return (0); 2456 } 2457 2458 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 2459 2460 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2461 "BootstrapMB: %p Completed %08x %08x %08x", 2462 hba->sli.sli4.bootstrapmb.virt, 2463 *iptr, *(iptr+1), *(iptr+2)); 2464 2465 return (tmo); 2466 2467 } /* emlxs_issue_bootstrap_mb() */ 2468 2469 2470 static int 2471 emlxs_init_bootstrap_mb(emlxs_hba_t *hba) 2472 { 2473 #ifdef FMA_SUPPORT 2474 emlxs_port_t *port = &PPORT; 2475 #endif /* FMA_SUPPORT */ 2476 uint32_t *iptr; 2477 uint32_t tmo; 2478 2479 if (emlxs_check_hdw_ready(hba)) { 2480 return (1); 2481 } 2482 2483 if (hba->flag & FC_BOOTSTRAPMB_INIT) { 2484 return (0); /* Already initialized */ 2485 } 2486 2487 /* NOTE: tmo is in 10ms ticks */ 2488 tmo = emlxs_check_bootstrap_ready(hba, 3000); 2489 if (tmo == 0) { 2490 return (1); 2491 } 2492 2493 /* Issue FW_INITIALIZE command */ 2494 2495 /* Special words to initialize bootstrap mbox MUST be little endian */ 2496 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 2497 *iptr = LE_SWAP32(FW_INITIALIZE_WORD0); 2498 *(iptr+1) = LE_SWAP32(FW_INITIALIZE_WORD1); 2499 2500 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, 2501 MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 2502 2503 emlxs_data_dump(port, "FW_INIT", (uint32_t *)iptr, 6, 0); 2504 if (!emlxs_issue_bootstrap_mb(hba, tmo)) { 2505 return (1); 2506 } 2507 2508 #ifdef FMA_SUPPORT 2509 if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle) 2510 != DDI_FM_OK) { 2511 EMLXS_MSGF(EMLXS_CONTEXT, 2512 &emlxs_invalid_dma_handle_msg, 2513 "init_bootstrap_mb: hdl=%p", 2514 hba->sli.sli4.bootstrapmb.dma_handle); 2515 return (1); 2516 } 2517 #endif 2518 hba->flag |= FC_BOOTSTRAPMB_INIT; 2519 return (0); 2520 2521 } /* emlxs_init_bootstrap_mb() */ 2522 2523 2524 2525 2526 static uint32_t 2527 emlxs_sli4_hba_init(emlxs_hba_t *hba) 2528 { 2529 int rc; 2530 uint16_t i; 2531 emlxs_port_t *vport; 2532 emlxs_config_t *cfg = &CFG; 2533 CHANNEL *cp; 2534 VPIobj_t *vpip; 2535 2536 /* Restart the adapter */ 2537 if (emlxs_sli4_hba_reset(hba, 1, 0, 0)) { 2538 return (1); 2539 } 2540 2541 for (i = 0; i < hba->chan_count; i++) { 2542 cp = &hba->chan[i]; 2543 cp->iopath = (void *)&hba->sli.sli4.wq[i]; 2544 } 2545 2546 /* Initialize all the port objects */ 2547 hba->vpi_max = 0; 2548 for (i = 0; i < MAX_VPORTS; i++) { 2549 vport = &VPORT(i); 2550 vport->hba = hba; 2551 vport->vpi = i; 2552 2553 vpip = &vport->VPIobj; 2554 vpip->index = i; 2555 vpip->VPI = i; 2556 vpip->port = vport; 2557 vpip->state = VPI_STATE_OFFLINE; 2558 vport->vpip = vpip; 2559 } 2560 2561 /* Set the max node count */ 2562 if (hba->max_nodes == 0) { 2563 if (cfg[CFG_NUM_NODES].current > 0) { 2564 hba->max_nodes = cfg[CFG_NUM_NODES].current; 2565 } else { 2566 hba->max_nodes = 4096; 2567 } 2568 } 2569 2570 rc = emlxs_init_bootstrap_mb(hba); 2571 if (rc) { 2572 return (rc); 2573 } 2574 2575 hba->sli.sli4.cfgFCOE.FCMap[0] = FCOE_FCF_MAP0; 2576 hba->sli.sli4.cfgFCOE.FCMap[1] = FCOE_FCF_MAP1; 2577 hba->sli.sli4.cfgFCOE.FCMap[2] = FCOE_FCF_MAP2; 2578 2579 if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == SLI_INTF_IF_TYPE_0) { 2580 /* Cache the UE MASK registers value for UE error detection */ 2581 hba->sli.sli4.ue_mask_lo = ddi_get32(hba->pci_acc_handle, 2582 (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_LO_OFFSET)); 2583 hba->sli.sli4.ue_mask_hi = ddi_get32(hba->pci_acc_handle, 2584 (uint32_t *)(hba->pci_addr + PCICFG_UE_MASK_HI_OFFSET)); 2585 } 2586 2587 return (0); 2588 2589 } /* emlxs_sli4_hba_init() */ 2590 2591 2592 /*ARGSUSED*/ 2593 static uint32_t 2594 emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, 2595 uint32_t quiesce) 2596 { 2597 emlxs_port_t *port = &PPORT; 2598 emlxs_port_t *vport; 2599 CHANNEL *cp; 2600 emlxs_config_t *cfg = &CFG; 2601 MAILBOXQ mboxq; 2602 uint32_t value; 2603 uint32_t i; 2604 uint32_t rc; 2605 uint16_t channelno; 2606 uint32_t status; 2607 uint32_t err1; 2608 uint32_t err2; 2609 uint8_t generate_event = 0; 2610 2611 if (!cfg[CFG_RESET_ENABLE].current) { 2612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2613 "Adapter reset disabled."); 2614 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2615 2616 return (1); 2617 } 2618 2619 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 2620 case SLI_INTF_IF_TYPE_0: 2621 if (quiesce == 0) { 2622 emlxs_sli4_hba_kill(hba); 2623 2624 /* 2625 * Initalize Hardware that will be used to bring 2626 * SLI4 online. 2627 */ 2628 rc = emlxs_init_bootstrap_mb(hba); 2629 if (rc) { 2630 return (rc); 2631 } 2632 } 2633 2634 bzero((void *)&mboxq, sizeof (MAILBOXQ)); 2635 emlxs_mb_resetport(hba, &mboxq); 2636 2637 if (quiesce == 0) { 2638 if (emlxs_sli4_issue_mbox_cmd(hba, &mboxq, 2639 MBX_POLL, 0) != MBX_SUCCESS) { 2640 /* Timeout occurred */ 2641 EMLXS_MSGF(EMLXS_CONTEXT, 2642 &emlxs_reset_failed_msg, 2643 "Timeout: RESET"); 2644 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2645 /* Log a dump event - not supported */ 2646 return (1); 2647 } 2648 } else { 2649 if (emlxs_sli4_issue_mbox_cmd4quiesce(hba, &mboxq, 2650 MBX_POLL, 0) != MBX_SUCCESS) { 2651 EMLXS_STATE_CHANGE(hba, FC_ERROR); 2652 /* Log a dump event - not supported */ 2653 return (1); 2654 } 2655 } 2656 emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0); 2657 break; 2658 2659 case SLI_INTF_IF_TYPE_2: 2660 case SLI_INTF_IF_TYPE_6: 2661 if (quiesce == 0) { 2662 emlxs_sli4_hba_kill(hba); 2663 } 2664 2665 rc = emlxs_check_hdw_ready(hba); 2666 if (rc > 1) { 2667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 2668 "Adapter not ready for reset."); 2669 return (1); 2670 } 2671 2672 if (rc == 1) { 2673 err1 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2674 hba->sli.sli4.ERR1_reg_addr); 2675 err2 = ddi_get32(hba->sli.sli4.bar0_acc_handle, 2676 hba->sli.sli4.ERR2_reg_addr); 2677 2678 /* Don't generate an event if dump was forced */ 2679 if ((err1 != 0x2) || (err2 != 0x2)) { 2680 generate_event = 1; 2681 } 2682 } 2683 2684 /* Reset the port now */ 2685 2686 mutex_enter(&EMLXS_PORT_LOCK); 2687 value = SLI_CNTL_INIT_PORT; 2688 2689 ddi_put32(hba->sli.sli4.bar0_acc_handle, 2690 hba->sli.sli4.CNTL_reg_addr, value); 2691 mutex_exit(&EMLXS_PORT_LOCK); 2692 2693 break; 2694 } 2695 2696 /* Reset the hba structure */ 2697 hba->flag &= FC_RESET_MASK; 2698 2699 for (channelno = 0; channelno < hba->chan_count; channelno++) { 2700 cp = &hba->chan[channelno]; 2701 cp->hba = hba; 2702 cp->channelno = channelno; 2703 } 2704 2705 hba->channel_tx_count = 0; 2706 hba->io_count = 0; 2707 hba->iodone_count = 0; 2708 hba->topology = 0; 2709 hba->linkspeed = 0; 2710 hba->heartbeat_active = 0; 2711 hba->discovery_timer = 0; 2712 hba->linkup_timer = 0; 2713 hba->loopback_tics = 0; 2714 2715 /* Specific to ATTO G5 boards */ 2716 if (hba->model_info.flags & EMLXS_GPIO_LEDS) { 2717 /* Assume the boot driver enabled all LEDs */ 2718 hba->gpio_current = 2719 EMLXS_GPIO_LO | EMLXS_GPIO_HI | EMLXS_GPIO_ACT; 2720 hba->gpio_desired = 0; 2721 hba->gpio_bit = 0; 2722 } 2723 2724 /* Reset the port objects */ 2725 for (i = 0; i < MAX_VPORTS; i++) { 2726 vport = &VPORT(i); 2727 2728 vport->flag &= EMLXS_PORT_RESET_MASK; 2729 vport->did = 0; 2730 vport->prev_did = 0; 2731 vport->lip_type = 0; 2732 bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); 2733 bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM)); 2734 2735 bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); 2736 vport->node_base.nlp_Rpi = 0; 2737 vport->node_base.nlp_DID = 0xffffff; 2738 vport->node_base.nlp_list_next = NULL; 2739 vport->node_base.nlp_list_prev = NULL; 2740 vport->node_base.nlp_active = 1; 2741 vport->node_count = 0; 2742 2743 if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) { 2744 vport->ub_count = EMLXS_UB_TOKEN_OFFSET; 2745 } 2746 } 2747 2748 if (emlxs_check_hdw_ready(hba)) { 2749 return (1); 2750 } 2751 2752 if (generate_event) { 2753 status = emlxs_sli4_read_status(hba); 2754 if (status & SLI_STATUS_DUMP_IMAGE_PRESENT) { 2755 emlxs_log_dump_event(port, NULL, 0); 2756 } 2757 } 2758 2759 return (0); 2760 2761 } /* emlxs_sli4_hba_reset */ 2762 2763 2764 #define SGL_CMD 0 2765 #define SGL_RESP 1 2766 #define SGL_DATA 2 2767 #define SGL_LAST 0x80 2768 2769 /*ARGSUSED*/ 2770 static ULP_SGE64 * 2771 emlxs_pkt_to_sgl(emlxs_port_t *port, fc_packet_t *pkt, ULP_SGE64 *sge, 2772 uint32_t sgl_type, uint32_t *pcnt) 2773 { 2774 #ifdef DEBUG_SGE 2775 emlxs_hba_t *hba = HBA; 2776 #endif /* DEBUG_SGE */ 2777 ddi_dma_cookie_t *cp; 2778 uint_t i; 2779 uint_t last; 2780 int32_t size; 2781 int32_t sge_size; 2782 uint64_t sge_addr; 2783 int32_t len; 2784 uint32_t cnt; 2785 uint_t cookie_cnt; 2786 ULP_SGE64 stage_sge; 2787 2788 last = sgl_type & SGL_LAST; 2789 sgl_type &= ~SGL_LAST; 2790 2791 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2792 switch (sgl_type) { 2793 case SGL_CMD: 2794 cp = pkt->pkt_cmd_cookie; 2795 cookie_cnt = pkt->pkt_cmd_cookie_cnt; 2796 size = (int32_t)pkt->pkt_cmdlen; 2797 break; 2798 2799 case SGL_RESP: 2800 cp = pkt->pkt_resp_cookie; 2801 cookie_cnt = pkt->pkt_resp_cookie_cnt; 2802 size = (int32_t)pkt->pkt_rsplen; 2803 break; 2804 2805 2806 case SGL_DATA: 2807 cp = pkt->pkt_data_cookie; 2808 cookie_cnt = pkt->pkt_data_cookie_cnt; 2809 size = (int32_t)pkt->pkt_datalen; 2810 break; 2811 2812 default: 2813 return (NULL); 2814 } 2815 2816 #else 2817 switch (sgl_type) { 2818 case SGL_CMD: 2819 cp = &pkt->pkt_cmd_cookie; 2820 cookie_cnt = 1; 2821 size = (int32_t)pkt->pkt_cmdlen; 2822 break; 2823 2824 case SGL_RESP: 2825 cp = &pkt->pkt_resp_cookie; 2826 cookie_cnt = 1; 2827 size = (int32_t)pkt->pkt_rsplen; 2828 break; 2829 2830 2831 case SGL_DATA: 2832 cp = &pkt->pkt_data_cookie; 2833 cookie_cnt = 1; 2834 size = (int32_t)pkt->pkt_datalen; 2835 break; 2836 2837 default: 2838 return (NULL); 2839 } 2840 #endif /* >= EMLXS_MODREV3 */ 2841 2842 stage_sge.offset = 0; 2843 stage_sge.type = 0; 2844 stage_sge.last = 0; 2845 cnt = 0; 2846 for (i = 0; i < cookie_cnt && size > 0; i++, cp++) { 2847 2848 sge_size = cp->dmac_size; 2849 sge_addr = cp->dmac_laddress; 2850 while (sge_size && size) { 2851 if (cnt) { 2852 /* Copy staged SGE before we build next one */ 2853 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 2854 (uint8_t *)sge, sizeof (ULP_SGE64)); 2855 sge++; 2856 } 2857 len = MIN(EMLXS_MAX_SGE_SIZE, sge_size); 2858 len = MIN(size, len); 2859 2860 stage_sge.addrHigh = 2861 PADDR_HI(sge_addr); 2862 stage_sge.addrLow = 2863 PADDR_LO(sge_addr); 2864 stage_sge.length = len; 2865 if (sgl_type == SGL_DATA) { 2866 stage_sge.offset = cnt; 2867 } 2868 #ifdef DEBUG_SGE 2869 emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge, 2870 4, 0); 2871 #endif /* DEBUG_SGE */ 2872 sge_addr += len; 2873 sge_size -= len; 2874 2875 cnt += len; 2876 size -= len; 2877 } 2878 } 2879 2880 if (last) { 2881 stage_sge.last = 1; 2882 } 2883 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, 2884 sizeof (ULP_SGE64)); 2885 2886 sge++; 2887 2888 if (pcnt) { 2889 *pcnt = cnt; 2890 } 2891 return (sge); 2892 2893 } /* emlxs_pkt_to_sgl */ 2894 2895 2896 /*ARGSUSED*/ 2897 uint32_t 2898 emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2899 { 2900 emlxs_hba_t *hba = HBA; 2901 fc_packet_t *pkt; 2902 XRIobj_t *xrip; 2903 ULP_SGE64 *sge; 2904 emlxs_wqe_t *wqe; 2905 IOCBQ *iocbq; 2906 ddi_dma_cookie_t *cp_cmd; 2907 ddi_dma_cookie_t *cp_data; 2908 uint64_t sge_addr; 2909 uint32_t cmd_cnt; 2910 uint32_t resp_cnt; 2911 2912 iocbq = (IOCBQ *) &sbp->iocbq; 2913 wqe = &iocbq->wqe; 2914 pkt = PRIV2PKT(sbp); 2915 xrip = sbp->xrip; 2916 sge = xrip->SGList->virt; 2917 2918 #if (EMLXS_MODREV >= EMLXS_MODREV3) 2919 cp_cmd = pkt->pkt_cmd_cookie; 2920 cp_data = pkt->pkt_data_cookie; 2921 #else 2922 cp_cmd = &pkt->pkt_cmd_cookie; 2923 cp_data = &pkt->pkt_data_cookie; 2924 #endif /* >= EMLXS_MODREV3 */ 2925 2926 iocbq = &sbp->iocbq; 2927 if (iocbq->flag & IOCB_FCP_CMD) { 2928 2929 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2930 return (1); 2931 } 2932 2933 /* CMD payload */ 2934 sge = emlxs_pkt_to_sgl(port, pkt, sge, SGL_CMD, &cmd_cnt); 2935 if (! sge) { 2936 return (1); 2937 } 2938 2939 /* DATA payload */ 2940 if (pkt->pkt_datalen != 0) { 2941 /* RSP payload */ 2942 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2943 SGL_RESP, &resp_cnt); 2944 if (! sge) { 2945 return (1); 2946 } 2947 2948 /* Data payload */ 2949 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2950 SGL_DATA | SGL_LAST, 0); 2951 if (! sge) { 2952 return (1); 2953 } 2954 sgl_done: 2955 if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) { 2956 sge_addr = cp_data->dmac_laddress; 2957 wqe->FirstData.addrHigh = PADDR_HI(sge_addr); 2958 wqe->FirstData.addrLow = PADDR_LO(sge_addr); 2959 wqe->FirstData.tus.f.bdeSize = 2960 cp_data->dmac_size; 2961 } 2962 } else { 2963 /* RSP payload */ 2964 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2965 SGL_RESP | SGL_LAST, &resp_cnt); 2966 if (! sge) { 2967 return (1); 2968 } 2969 } 2970 2971 wqe->un.FcpCmd.Payload.addrHigh = 2972 PADDR_HI(cp_cmd->dmac_laddress); 2973 wqe->un.FcpCmd.Payload.addrLow = 2974 PADDR_LO(cp_cmd->dmac_laddress); 2975 wqe->un.FcpCmd.Payload.tus.f.bdeSize = cmd_cnt; 2976 wqe->un.FcpCmd.PayloadLength = cmd_cnt + resp_cnt; 2977 2978 } else { 2979 2980 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2981 /* CMD payload */ 2982 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2983 SGL_CMD | SGL_LAST, &cmd_cnt); 2984 if (! sge) { 2985 return (1); 2986 } 2987 } else { 2988 /* CMD payload */ 2989 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2990 SGL_CMD, &cmd_cnt); 2991 if (! sge) { 2992 return (1); 2993 } 2994 2995 /* RSP payload */ 2996 sge = emlxs_pkt_to_sgl(port, pkt, sge, 2997 SGL_RESP | SGL_LAST, &resp_cnt); 2998 if (! sge) { 2999 return (1); 3000 } 3001 wqe->un.GenReq.PayloadLength = cmd_cnt; 3002 } 3003 3004 wqe->un.GenReq.Payload.addrHigh = 3005 PADDR_HI(cp_cmd->dmac_laddress); 3006 wqe->un.GenReq.Payload.addrLow = 3007 PADDR_LO(cp_cmd->dmac_laddress); 3008 wqe->un.GenReq.Payload.tus.f.bdeSize = cmd_cnt; 3009 } 3010 return (0); 3011 } /* emlxs_sli4_bde_setup */ 3012 3013 3014 3015 3016 #ifdef SFCT_SUPPORT 3017 /*ARGSUSED*/ 3018 static uint32_t 3019 emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 3020 { 3021 emlxs_hba_t *hba = HBA; 3022 emlxs_wqe_t *wqe; 3023 ULP_SGE64 stage_sge; 3024 ULP_SGE64 *sge; 3025 IOCB *iocb; 3026 IOCBQ *iocbq; 3027 MATCHMAP *mp; 3028 MATCHMAP *fct_mp; 3029 XRIobj_t *xrip; 3030 uint64_t sge_addr; 3031 uint32_t sge_size; 3032 uint32_t cnt; 3033 uint32_t len; 3034 uint32_t size; 3035 uint32_t *xrdy_vaddr; 3036 stmf_data_buf_t *dbuf; 3037 3038 iocbq = &sbp->iocbq; 3039 iocb = &iocbq->iocb; 3040 wqe = &iocbq->wqe; 3041 xrip = sbp->xrip; 3042 3043 if (!sbp->fct_buf) { 3044 return (0); 3045 } 3046 3047 size = sbp->fct_buf->db_data_size; 3048 3049 /* 3050 * The hardware will automaticlly round up 3051 * to multiple of 4. 3052 * 3053 * if (size & 3) { 3054 * size = (size + 3) & 0xfffffffc; 3055 * } 3056 */ 3057 fct_mp = (MATCHMAP *)sbp->fct_buf->db_port_private; 3058 3059 if (sbp->fct_buf->db_sglist_length != 1) { 3060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 3061 "fct_bde_setup: Only 1 sglist entry supported: %d", 3062 sbp->fct_buf->db_sglist_length); 3063 return (1); 3064 } 3065 3066 sge = xrip->SGList->virt; 3067 3068 if (iocb->ULPCOMMAND == CMD_FCP_TRECEIVE64_CX) { 3069 3070 mp = emlxs_mem_buf_alloc(hba, EMLXS_XFER_RDY_SIZE); 3071 if (!mp || !mp->virt || !mp->phys) { 3072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 3073 "fct_bde_setup: Cannot allocate XRDY memory"); 3074 return (1); 3075 } 3076 /* Save the MATCHMAP info to free this memory later */ 3077 iocbq->bp = mp; 3078 3079 /* Point to XRDY payload */ 3080 xrdy_vaddr = (uint32_t *)(mp->virt); 3081 3082 /* Fill in burstsize in payload */ 3083 *xrdy_vaddr++ = 0; 3084 *xrdy_vaddr++ = LE_SWAP32(size); 3085 *xrdy_vaddr = 0; 3086 3087 /* First 2 SGEs are XRDY and SKIP */ 3088 stage_sge.addrHigh = PADDR_HI(mp->phys); 3089 stage_sge.addrLow = PADDR_LO(mp->phys); 3090 stage_sge.length = EMLXS_XFER_RDY_SIZE; 3091 stage_sge.offset = 0; 3092 stage_sge.type = 0; 3093 stage_sge.last = 0; 3094 3095 /* Words 0-3 */ 3096 wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh; 3097 wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow; 3098 wqe->un.FcpCmd.Payload.tus.f.bdeSize = EMLXS_XFER_RDY_SIZE; 3099 wqe->un.FcpCmd.PayloadLength = EMLXS_XFER_RDY_SIZE; 3100 3101 } else { /* CMD_FCP_TSEND64_CX */ 3102 /* First 2 SGEs are SKIP */ 3103 stage_sge.addrHigh = 0; 3104 stage_sge.addrLow = 0; 3105 stage_sge.length = 0; 3106 stage_sge.offset = 0; 3107 stage_sge.type = EMLXS_SGE_TYPE_SKIP; 3108 stage_sge.last = 0; 3109 3110 /* Words 0-3 */ 3111 wqe->un.FcpCmd.Payload.addrHigh = PADDR_HI(fct_mp->phys); 3112 wqe->un.FcpCmd.Payload.addrLow = PADDR_LO(fct_mp->phys); 3113 3114 /* The BDE should match the contents of the first SGE payload */ 3115 len = MIN(EMLXS_MAX_SGE_SIZE, size); 3116 wqe->un.FcpCmd.Payload.tus.f.bdeSize = len; 3117 3118 /* The PayloadLength should be set to 0 for TSEND64. */ 3119 wqe->un.FcpCmd.PayloadLength = 0; 3120 } 3121 3122 dbuf = sbp->fct_buf; 3123 /* 3124 * TotalTransferCount equals to Relative Offset field (Word 4) 3125 * in both TSEND64 and TRECEIVE64 WQE. 3126 */ 3127 wqe->un.FcpCmd.TotalTransferCount = dbuf->db_relative_offset; 3128 3129 /* Copy staged SGE into SGL */ 3130 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 3131 (uint8_t *)sge, sizeof (ULP_SGE64)); 3132 sge++; 3133 3134 stage_sge.addrHigh = 0; 3135 stage_sge.addrLow = 0; 3136 stage_sge.length = 0; 3137 stage_sge.offset = 0; 3138 stage_sge.type = EMLXS_SGE_TYPE_SKIP; 3139 stage_sge.last = 0; 3140 3141 /* Copy staged SGE into SGL */ 3142 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 3143 (uint8_t *)sge, sizeof (ULP_SGE64)); 3144 sge++; 3145 3146 sge_size = size; 3147 sge_addr = fct_mp->phys; 3148 cnt = 0; 3149 3150 /* Build SGEs */ 3151 while (sge_size) { 3152 if (cnt) { 3153 /* Copy staged SGE before we build next one */ 3154 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 3155 (uint8_t *)sge, sizeof (ULP_SGE64)); 3156 sge++; 3157 } 3158 3159 len = MIN(EMLXS_MAX_SGE_SIZE, sge_size); 3160 3161 stage_sge.addrHigh = PADDR_HI(sge_addr); 3162 stage_sge.addrLow = PADDR_LO(sge_addr); 3163 stage_sge.length = len; 3164 stage_sge.offset = cnt; 3165 stage_sge.type = EMLXS_SGE_TYPE_DATA; 3166 3167 sge_addr += len; 3168 sge_size -= len; 3169 cnt += len; 3170 } 3171 3172 stage_sge.last = 1; 3173 3174 if (hba->sli.sli4.flag & EMLXS_SLI4_PHON) { 3175 wqe->FirstData.addrHigh = stage_sge.addrHigh; 3176 wqe->FirstData.addrLow = stage_sge.addrLow; 3177 wqe->FirstData.tus.f.bdeSize = stage_sge.length; 3178 } 3179 /* Copy staged SGE into SGL */ 3180 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 3181 (uint8_t *)sge, sizeof (ULP_SGE64)); 3182 3183 return (0); 3184 3185 } /* emlxs_sli4_fct_bde_setup */ 3186 #endif /* SFCT_SUPPORT */ 3187 3188 3189 static void 3190 emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 3191 { 3192 emlxs_port_t *port = &PPORT; 3193 emlxs_buf_t *sbp; 3194 uint32_t channelno; 3195 int32_t throttle; 3196 emlxs_wqe_t *wqe; 3197 emlxs_wqe_t *wqeslot; 3198 WQ_DESC_t *wq; 3199 uint32_t flag; 3200 uint16_t next_wqe; 3201 off_t offset; 3202 #ifdef NODE_THROTTLE_SUPPORT 3203 int32_t node_throttle; 3204 NODELIST *marked_node = NULL; 3205 #endif /* NODE_THROTTLE_SUPPORT */ 3206 3207 3208 channelno = cp->channelno; 3209 wq = (WQ_DESC_t *)cp->iopath; 3210 3211 #ifdef DEBUG_FASTPATH 3212 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3213 "ISSUE WQE channel: %x %p", channelno, wq); 3214 #endif /* DEBUG_FASTPATH */ 3215 3216 throttle = 0; 3217 3218 /* Check if FCP ring and adapter is not ready */ 3219 /* We may use any ring for FCP_CMD */ 3220 if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) { 3221 if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port || 3222 (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) { 3223 emlxs_tx_put(iocbq, 1); 3224 return; 3225 } 3226 } 3227 3228 /* Attempt to acquire CMD_RING lock */ 3229 if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) { 3230 /* Queue it for later */ 3231 if (iocbq) { 3232 if ((hba->io_count - 3233 hba->channel_tx_count) > 10) { 3234 emlxs_tx_put(iocbq, 1); 3235 return; 3236 } else { 3237 3238 mutex_enter(&EMLXS_QUE_LOCK(channelno)); 3239 } 3240 } else { 3241 return; 3242 } 3243 } 3244 /* EMLXS_QUE_LOCK acquired */ 3245 3246 /* Throttle check only applies to non special iocb */ 3247 if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) { 3248 /* Check if HBA is full */ 3249 throttle = hba->io_throttle - hba->io_active; 3250 if (throttle <= 0) { 3251 /* Hitting adapter throttle limit */ 3252 /* Queue it for later */ 3253 if (iocbq) { 3254 emlxs_tx_put(iocbq, 1); 3255 } 3256 3257 goto busy; 3258 } 3259 } 3260 3261 /* Check to see if we have room for this WQE */ 3262 next_wqe = wq->host_index + 1; 3263 if (next_wqe >= wq->max_index) { 3264 next_wqe = 0; 3265 } 3266 3267 if (next_wqe == wq->port_index) { 3268 /* Queue it for later */ 3269 if (iocbq) { 3270 emlxs_tx_put(iocbq, 1); 3271 } 3272 goto busy; 3273 } 3274 3275 /* 3276 * We have a command ring slot available 3277 * Make sure we have an iocb to send 3278 */ 3279 if (iocbq) { 3280 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3281 3282 /* Check if the ring already has iocb's waiting */ 3283 if (cp->nodeq.q_first != NULL) { 3284 /* Put the current iocbq on the tx queue */ 3285 emlxs_tx_put(iocbq, 0); 3286 3287 /* 3288 * Attempt to replace it with the next iocbq 3289 * in the tx queue 3290 */ 3291 iocbq = emlxs_tx_get(cp, 0); 3292 } 3293 3294 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3295 } else { 3296 iocbq = emlxs_tx_get(cp, 1); 3297 } 3298 3299 sendit: 3300 /* Process each iocbq */ 3301 while (iocbq) { 3302 sbp = iocbq->sbp; 3303 3304 #ifdef NODE_THROTTLE_SUPPORT 3305 if (sbp && sbp->node && sbp->node->io_throttle) { 3306 node_throttle = sbp->node->io_throttle - 3307 sbp->node->io_active; 3308 if (node_throttle <= 0) { 3309 /* Node is busy */ 3310 /* Queue this iocb and get next iocb from */ 3311 /* channel */ 3312 3313 if (!marked_node) { 3314 marked_node = sbp->node; 3315 } 3316 3317 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3318 emlxs_tx_put(iocbq, 0); 3319 3320 if (cp->nodeq.q_first == marked_node) { 3321 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3322 goto busy; 3323 } 3324 3325 iocbq = emlxs_tx_get(cp, 0); 3326 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3327 continue; 3328 } 3329 } 3330 marked_node = 0; 3331 #endif /* NODE_THROTTLE_SUPPORT */ 3332 3333 wqe = &iocbq->wqe; 3334 #ifdef DEBUG_FASTPATH 3335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3336 "ISSUE QID %d WQE iotag:%x xri:%d", wq->qid, 3337 wqe->RequestTag, wqe->XRITag); 3338 #endif /* DEBUG_FASTPATH */ 3339 3340 if (sbp) { 3341 /* If exchange removed after wqe was prep'ed, drop it */ 3342 if (!(sbp->xrip)) { 3343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3344 "Xmit WQE iotag:%x xri:%d aborted", 3345 wqe->RequestTag, wqe->XRITag); 3346 3347 /* Get next iocb from the tx queue */ 3348 iocbq = emlxs_tx_get(cp, 1); 3349 continue; 3350 } 3351 3352 if (sbp->pkt_flags & PACKET_DELAY_REQUIRED) { 3353 3354 /* Perform delay */ 3355 if ((channelno == hba->channel_els) && 3356 !(iocbq->flag & IOCB_FCP_CMD)) { 3357 drv_usecwait(100000); 3358 } else { 3359 drv_usecwait(20000); 3360 } 3361 } 3362 3363 /* Check for ULP pkt request */ 3364 mutex_enter(&sbp->mtx); 3365 3366 if (sbp->node == NULL) { 3367 /* Set node to base node by default */ 3368 iocbq->node = (void *)&port->node_base; 3369 sbp->node = (void *)&port->node_base; 3370 } 3371 3372 sbp->pkt_flags |= PACKET_IN_CHIPQ; 3373 mutex_exit(&sbp->mtx); 3374 3375 atomic_inc_32(&hba->io_active); 3376 #ifdef NODE_THROTTLE_SUPPORT 3377 if (sbp->node) { 3378 atomic_inc_32(&sbp->node->io_active); 3379 } 3380 #endif /* NODE_THROTTLE_SUPPORT */ 3381 3382 sbp->xrip->flag |= EMLXS_XRI_PENDING_IO; 3383 #ifdef SFCT_SUPPORT 3384 #ifdef FCT_IO_TRACE 3385 if (sbp->fct_cmd) { 3386 emlxs_fct_io_trace(port, sbp->fct_cmd, 3387 EMLXS_FCT_IOCB_ISSUED); 3388 emlxs_fct_io_trace(port, sbp->fct_cmd, 3389 icmd->ULPCOMMAND); 3390 } 3391 #endif /* FCT_IO_TRACE */ 3392 #endif /* SFCT_SUPPORT */ 3393 cp->hbaSendCmd_sbp++; 3394 iocbq->channel = cp; 3395 } else { 3396 cp->hbaSendCmd++; 3397 } 3398 3399 flag = iocbq->flag; 3400 3401 /* 3402 * At this point, we have a command ring slot available 3403 * and an iocb to send 3404 */ 3405 wq->release_depth--; 3406 if (wq->release_depth == 0) { 3407 wq->release_depth = WQE_RELEASE_DEPTH; 3408 wqe->WQEC = 1; 3409 } 3410 3411 HBASTATS.IocbIssued[channelno]++; 3412 wq->num_proc++; 3413 3414 /* Send the iocb */ 3415 wqeslot = (emlxs_wqe_t *)wq->addr.virt; 3416 wqeslot += wq->host_index; 3417 3418 wqe->CQId = wq->cqid; 3419 if (hba->sli.sli4.param.PHWQ) { 3420 WQE_PHWQ_WQID(wqe, wq->qid); 3421 } 3422 BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot, 3423 sizeof (emlxs_wqe_t)); 3424 #ifdef DEBUG_WQE 3425 emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0); 3426 #endif /* DEBUG_WQE */ 3427 offset = (off_t)((uint64_t)((unsigned long) 3428 wq->addr.virt) - 3429 (uint64_t)((unsigned long) 3430 hba->sli.sli4.slim2.virt)); 3431 3432 EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset, 3433 4096, DDI_DMA_SYNC_FORDEV); 3434 3435 /* 3436 * After this, the sbp / iocb / wqe should not be 3437 * accessed in the xmit path. 3438 */ 3439 3440 /* Ring the WQ Doorbell */ 3441 emlxs_sli4_write_wqdb(hba, wq->qid, 1, wq->host_index); 3442 wq->host_index = next_wqe; 3443 3444 if (!sbp) { 3445 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 3446 } 3447 3448 if (iocbq && (!(flag & IOCB_SPECIAL))) { 3449 /* Check if HBA is full */ 3450 throttle = hba->io_throttle - hba->io_active; 3451 if (throttle <= 0) { 3452 goto busy; 3453 } 3454 } 3455 3456 /* Check to see if we have room for another WQE */ 3457 next_wqe++; 3458 if (next_wqe >= wq->max_index) { 3459 next_wqe = 0; 3460 } 3461 3462 if (next_wqe == wq->port_index) { 3463 /* Queue it for later */ 3464 goto busy; 3465 } 3466 3467 /* Get the next iocb from the tx queue if there is one */ 3468 iocbq = emlxs_tx_get(cp, 1); 3469 } 3470 3471 mutex_exit(&EMLXS_QUE_LOCK(channelno)); 3472 3473 return; 3474 3475 busy: 3476 wq->num_busy++; 3477 if (throttle <= 0) { 3478 HBASTATS.IocbThrottled++; 3479 } else { 3480 HBASTATS.IocbRingFull[channelno]++; 3481 } 3482 3483 mutex_exit(&EMLXS_QUE_LOCK(channelno)); 3484 3485 return; 3486 3487 } /* emlxs_sli4_issue_iocb_cmd() */ 3488 3489 3490 /*ARGSUSED*/ 3491 static uint32_t 3492 emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb, 3493 uint32_t tmo) 3494 { 3495 emlxs_hba_t *hba = HBA; 3496 MAILBOXQ *mbq; 3497 MAILBOX4 *mb4; 3498 MATCHMAP *mp; 3499 uint32_t *iptr; 3500 off_t offset; 3501 3502 mbq = (MAILBOXQ *)mb; 3503 mb4 = (MAILBOX4 *)mb; 3504 mp = (MATCHMAP *) mbq->nonembed; 3505 hba->mbox_mqe = (void *)mqe; 3506 3507 if ((mb->mbxCommand != MBX_SLI_CONFIG) || 3508 (mb4->un.varSLIConfig.be.embedded)) { 3509 /* 3510 * If this is an embedded mbox, everything should fit 3511 * into the mailbox area. 3512 */ 3513 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe, 3514 MAILBOX_CMD_SLI4_BSIZE); 3515 3516 EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0, 3517 4096, DDI_DMA_SYNC_FORDEV); 3518 3519 if (mb->mbxCommand != MBX_HEARTBEAT) { 3520 emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe, 3521 18, 0); 3522 } 3523 } else { 3524 /* SLI_CONFIG and non-embedded */ 3525 3526 /* 3527 * If this is not embedded, the MQ area 3528 * MUST contain a SGE pointer to a larger area for the 3529 * non-embedded mailbox command. 3530 * mp will point to the actual mailbox command which 3531 * should be copied into the non-embedded area. 3532 */ 3533 mb4->un.varSLIConfig.be.sge_cnt = 1; 3534 mb4->un.varSLIConfig.be.payload_length = mp->size; 3535 iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req; 3536 *iptr++ = (uint32_t)PADDR_LO(mp->phys); 3537 *iptr++ = (uint32_t)PADDR_HI(mp->phys); 3538 *iptr = mp->size; 3539 3540 BE_SWAP32_BUFFER(mp->virt, mp->size); 3541 3542 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, 3543 DDI_DMA_SYNC_FORDEV); 3544 3545 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe, 3546 MAILBOX_CMD_SLI4_BSIZE); 3547 3548 offset = (off_t)((uint64_t)((unsigned long) 3549 hba->sli.sli4.mq.addr.virt) - 3550 (uint64_t)((unsigned long) 3551 hba->sli.sli4.slim2.virt)); 3552 3553 EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset, 3554 4096, DDI_DMA_SYNC_FORDEV); 3555 3556 emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0); 3557 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3558 "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt)); 3559 emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0); 3560 } 3561 3562 /* Ring the MQ Doorbell */ 3563 if (mb->mbxCommand != MBX_HEARTBEAT) { 3564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 3565 "MQ RING: Qid %04x", hba->sli.sli4.mq.qid); 3566 } 3567 3568 emlxs_sli4_write_mqdb(hba, hba->sli.sli4.mq.qid, 1); 3569 3570 return (MBX_SUCCESS); 3571 3572 } /* emlxs_sli4_issue_mq() */ 3573 3574 3575 /*ARGSUSED*/ 3576 static uint32_t 3577 emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) 3578 { 3579 emlxs_port_t *port = &PPORT; 3580 MAILBOXQ *mbq; 3581 MAILBOX4 *mb4; 3582 MATCHMAP *mp = NULL; 3583 uint32_t *iptr; 3584 int nonembed = 0; 3585 3586 mbq = (MAILBOXQ *)mb; 3587 mb4 = (MAILBOX4 *)mb; 3588 mp = (MATCHMAP *) mbq->nonembed; 3589 hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt; 3590 3591 if ((mb->mbxCommand != MBX_SLI_CONFIG) || 3592 (mb4->un.varSLIConfig.be.embedded)) { 3593 /* 3594 * If this is an embedded mbox, everything should fit 3595 * into the bootstrap mailbox area. 3596 */ 3597 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 3598 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr, 3599 MAILBOX_CMD_SLI4_BSIZE); 3600 3601 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, 3602 MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV); 3603 emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0); 3604 } else { 3605 /* 3606 * If this is not embedded, the bootstrap mailbox area 3607 * MUST contain a SGE pointer to a larger area for the 3608 * non-embedded mailbox command. 3609 * mp will point to the actual mailbox command which 3610 * should be copied into the non-embedded area. 3611 */ 3612 nonembed = 1; 3613 mb4->un.varSLIConfig.be.sge_cnt = 1; 3614 mb4->un.varSLIConfig.be.payload_length = mp->size; 3615 iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req; 3616 *iptr++ = (uint32_t)PADDR_LO(mp->phys); 3617 *iptr++ = (uint32_t)PADDR_HI(mp->phys); 3618 *iptr = mp->size; 3619 3620 BE_SWAP32_BUFFER(mp->virt, mp->size); 3621 3622 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, 3623 DDI_DMA_SYNC_FORDEV); 3624 3625 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 3626 BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)iptr, 3627 MAILBOX_CMD_SLI4_BSIZE); 3628 3629 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, 3630 EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE, 3631 DDI_DMA_SYNC_FORDEV); 3632 3633 emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0); 3634 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3635 "Extension Addr %p %p", mp->phys, 3636 (uint32_t *)((uint8_t *)mp->virt)); 3637 iptr = (uint32_t *)((uint8_t *)mp->virt); 3638 emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0); 3639 } 3640 3641 3642 /* NOTE: tmo is in 10ms ticks */ 3643 if (!emlxs_issue_bootstrap_mb(hba, tmo)) { 3644 return (MBX_TIMEOUT); 3645 } 3646 3647 if ((mb->mbxCommand != MBX_SLI_CONFIG) || 3648 (mb4->un.varSLIConfig.be.embedded)) { 3649 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, 3650 MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORKERNEL); 3651 3652 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 3653 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb, 3654 MAILBOX_CMD_SLI4_BSIZE); 3655 3656 emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0); 3657 3658 } else { 3659 EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, 3660 EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE, 3661 DDI_DMA_SYNC_FORKERNEL); 3662 3663 EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, 3664 DDI_DMA_SYNC_FORKERNEL); 3665 3666 BE_SWAP32_BUFFER(mp->virt, mp->size); 3667 3668 iptr = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; 3669 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb, 3670 MAILBOX_CMD_SLI4_BSIZE); 3671 3672 emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0); 3673 iptr = (uint32_t *)((uint8_t *)mp->virt); 3674 emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0); 3675 } 3676 3677 #ifdef FMA_SUPPORT 3678 if (nonembed && mp) { 3679 if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 3680 != DDI_FM_OK) { 3681 EMLXS_MSGF(EMLXS_CONTEXT, 3682 &emlxs_invalid_dma_handle_msg, 3683 "sli4_issue_bootstrap: mp_hdl=%p", 3684 mp->dma_handle); 3685 return (MBXERR_DMA_ERROR); 3686 } 3687 } 3688 3689 if (emlxs_fm_check_dma_handle(hba, 3690 hba->sli.sli4.bootstrapmb.dma_handle) 3691 != DDI_FM_OK) { 3692 EMLXS_MSGF(EMLXS_CONTEXT, 3693 &emlxs_invalid_dma_handle_msg, 3694 "sli4_issue_bootstrap: hdl=%p", 3695 hba->sli.sli4.bootstrapmb.dma_handle); 3696 return (MBXERR_DMA_ERROR); 3697 } 3698 #endif 3699 3700 return (MBX_SUCCESS); 3701 3702 } /* emlxs_sli4_issue_bootstrap() */ 3703 3704 3705 /*ARGSUSED*/ 3706 static uint32_t 3707 emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, 3708 uint32_t tmo) 3709 { 3710 emlxs_port_t *port; 3711 MAILBOX4 *mb4; 3712 MAILBOX *mb; 3713 mbox_rsp_hdr_t *hdr_rsp; 3714 MATCHMAP *mp; 3715 uint32_t *iptr; 3716 uint32_t rc; 3717 uint32_t i; 3718 uint32_t tmo_local; 3719 3720 if (!mbq->port) { 3721 mbq->port = &PPORT; 3722 } 3723 3724 port = (emlxs_port_t *)mbq->port; 3725 3726 mb4 = (MAILBOX4 *)mbq; 3727 mb = (MAILBOX *)mbq; 3728 3729 mb->mbxStatus = MBX_SUCCESS; 3730 rc = MBX_SUCCESS; 3731 3732 /* Check for minimum timeouts */ 3733 switch (mb->mbxCommand) { 3734 /* Mailbox commands that erase/write flash */ 3735 case MBX_DOWN_LOAD: 3736 case MBX_UPDATE_CFG: 3737 case MBX_LOAD_AREA: 3738 case MBX_LOAD_EXP_ROM: 3739 case MBX_WRITE_NV: 3740 case MBX_FLASH_WR_ULA: 3741 case MBX_DEL_LD_ENTRY: 3742 case MBX_LOAD_SM: 3743 case MBX_DUMP_MEMORY: 3744 case MBX_WRITE_VPARMS: 3745 case MBX_ACCESS_VDATA: 3746 if (tmo < 300) { 3747 tmo = 300; 3748 } 3749 break; 3750 3751 case MBX_SLI_CONFIG: { 3752 mbox_req_hdr_t *hdr_req; 3753 3754 hdr_req = (mbox_req_hdr_t *) 3755 &mb4->un.varSLIConfig.be.un_hdr.hdr_req; 3756 3757 if (hdr_req->subsystem == IOCTL_SUBSYSTEM_COMMON) { 3758 switch (hdr_req->opcode) { 3759 case COMMON_OPCODE_WRITE_OBJ: 3760 case COMMON_OPCODE_READ_OBJ: 3761 case COMMON_OPCODE_READ_OBJ_LIST: 3762 case COMMON_OPCODE_DELETE_OBJ: 3763 case COMMON_OPCODE_SET_BOOT_CFG: 3764 case COMMON_OPCODE_GET_PROFILE_CFG: 3765 case COMMON_OPCODE_SET_PROFILE_CFG: 3766 case COMMON_OPCODE_GET_PROFILE_LIST: 3767 case COMMON_OPCODE_SET_ACTIVE_PROFILE: 3768 case COMMON_OPCODE_GET_PROFILE_CAPS: 3769 case COMMON_OPCODE_GET_MR_PROFILE_CAPS: 3770 case COMMON_OPCODE_SET_MR_PROFILE_CAPS: 3771 case COMMON_OPCODE_SET_FACTORY_PROFILE_CFG: 3772 case COMMON_OPCODE_SEND_ACTIVATION: 3773 case COMMON_OPCODE_RESET_LICENSES: 3774 case COMMON_OPCODE_SET_PHYSICAL_LINK_CFG_V1: 3775 case COMMON_OPCODE_GET_VPD_DATA: 3776 if (tmo < 300) { 3777 tmo = 300; 3778 } 3779 break; 3780 default: 3781 if (tmo < 30) { 3782 tmo = 30; 3783 } 3784 } 3785 } else if (hdr_req->subsystem == IOCTL_SUBSYSTEM_FCOE) { 3786 switch (hdr_req->opcode) { 3787 case FCOE_OPCODE_SET_FCLINK_SETTINGS: 3788 if (tmo < 300) { 3789 tmo = 300; 3790 } 3791 break; 3792 default: 3793 if (tmo < 30) { 3794 tmo = 30; 3795 } 3796 } 3797 } else { 3798 if (tmo < 30) { 3799 tmo = 30; 3800 } 3801 } 3802 3803 /* 3804 * Also: VENDOR_MANAGE_FFV (0x13, 0x02) (not currently used) 3805 */ 3806 3807 break; 3808 } 3809 default: 3810 if (tmo < 30) { 3811 tmo = 30; 3812 } 3813 break; 3814 } 3815 3816 /* Convert tmo seconds to 10 millisecond tics */ 3817 tmo_local = tmo * 100; 3818 3819 mutex_enter(&EMLXS_PORT_LOCK); 3820 3821 /* Adjust wait flag */ 3822 if (flag != MBX_NOWAIT) { 3823 if (hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED) { 3824 flag = MBX_SLEEP; 3825 } else { 3826 flag = MBX_POLL; 3827 } 3828 } else { 3829 /* Must have interrupts enabled to perform MBX_NOWAIT */ 3830 if (!(hba->sli.sli4.flag & EMLXS_SLI4_INTR_ENABLED)) { 3831 3832 mb->mbxStatus = MBX_HARDWARE_ERROR; 3833 mutex_exit(&EMLXS_PORT_LOCK); 3834 3835 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3836 "Interrupts disabled. %s failed.", 3837 emlxs_mb_cmd_xlate(mb->mbxCommand)); 3838 3839 return (MBX_HARDWARE_ERROR); 3840 } 3841 } 3842 3843 /* Check for hardware error ; special case SLI_CONFIG */ 3844 if ((hba->flag & FC_HARDWARE_ERROR) && 3845 ! ((mb4->mbxCommand == MBX_SLI_CONFIG) && 3846 (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode == 3847 COMMON_OPCODE_RESET))) { 3848 mb->mbxStatus = MBX_HARDWARE_ERROR; 3849 3850 mutex_exit(&EMLXS_PORT_LOCK); 3851 3852 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3853 "Hardware error reported. %s failed. status=%x mb=%p", 3854 emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb); 3855 3856 return (MBX_HARDWARE_ERROR); 3857 } 3858 3859 if (hba->mbox_queue_flag) { 3860 /* If we are not polling, then queue it for later */ 3861 if (flag == MBX_NOWAIT) { 3862 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3863 "Busy. %s: mb=%p NoWait.", 3864 emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3865 3866 emlxs_mb_put(hba, mbq); 3867 3868 HBASTATS.MboxBusy++; 3869 3870 mutex_exit(&EMLXS_PORT_LOCK); 3871 3872 return (MBX_BUSY); 3873 } 3874 3875 while (hba->mbox_queue_flag) { 3876 mutex_exit(&EMLXS_PORT_LOCK); 3877 3878 if (tmo_local-- == 0) { 3879 EMLXS_MSGF(EMLXS_CONTEXT, 3880 &emlxs_mbox_event_msg, 3881 "Timeout. %s: mb=%p tmo=%d Waiting.", 3882 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3883 tmo); 3884 3885 /* Non-lethalStatus mailbox timeout */ 3886 /* Does not indicate a hardware error */ 3887 mb->mbxStatus = MBX_TIMEOUT; 3888 return (MBX_TIMEOUT); 3889 } 3890 3891 BUSYWAIT_MS(10); 3892 mutex_enter(&EMLXS_PORT_LOCK); 3893 3894 /* Check for hardware error ; special case SLI_CONFIG */ 3895 if ((hba->flag & FC_HARDWARE_ERROR) && 3896 ! ((mb4->mbxCommand == MBX_SLI_CONFIG) && 3897 (mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode == 3898 COMMON_OPCODE_RESET))) { 3899 mb->mbxStatus = MBX_HARDWARE_ERROR; 3900 3901 mutex_exit(&EMLXS_PORT_LOCK); 3902 3903 EMLXS_MSGF(EMLXS_CONTEXT, 3904 &emlxs_mbox_detail_msg, 3905 "Hardware error reported. %s failed. " 3906 "status=%x mb=%p", 3907 emlxs_mb_cmd_xlate(mb->mbxCommand), 3908 mb->mbxStatus, mb); 3909 3910 return (MBX_HARDWARE_ERROR); 3911 } 3912 } 3913 } 3914 3915 /* Initialize mailbox area */ 3916 emlxs_mb_init(hba, mbq, flag, tmo); 3917 3918 if (mb->mbxCommand == MBX_DOWN_LINK) { 3919 hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK; 3920 } 3921 3922 mutex_exit(&EMLXS_PORT_LOCK); 3923 switch (flag) { 3924 3925 case MBX_NOWAIT: 3926 if (mb->mbxCommand != MBX_HEARTBEAT) { 3927 if (mb->mbxCommand != MBX_DOWN_LOAD 3928 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 3929 EMLXS_MSGF(EMLXS_CONTEXT, 3930 &emlxs_mbox_detail_msg, 3931 "Sending. %s: mb=%p NoWait. embedded %d", 3932 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3933 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 3934 (mb4->un.varSLIConfig.be.embedded))); 3935 } 3936 } 3937 3938 iptr = hba->sli.sli4.mq.addr.virt; 3939 iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE); 3940 hba->sli.sli4.mq.host_index++; 3941 if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) { 3942 hba->sli.sli4.mq.host_index = 0; 3943 } 3944 3945 if (mbq->bp) { 3946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3947 "BDE virt %p phys %p size x%x", 3948 ((MATCHMAP *)mbq->bp)->virt, 3949 ((MATCHMAP *)mbq->bp)->phys, 3950 ((MATCHMAP *)mbq->bp)->size); 3951 emlxs_data_dump(port, "DATA", 3952 (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0); 3953 } 3954 rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local); 3955 break; 3956 3957 case MBX_POLL: 3958 if (mb->mbxCommand != MBX_DOWN_LOAD 3959 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 3960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3961 "Sending. %s: mb=%p Poll. embedded %d", 3962 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3963 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 3964 (mb4->un.varSLIConfig.be.embedded))); 3965 } 3966 3967 rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local); 3968 3969 /* Clean up the mailbox area */ 3970 if (rc == MBX_TIMEOUT) { 3971 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3972 "Timeout. %s: mb=%p tmo=%x Poll. embedded %d", 3973 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo, 3974 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 3975 (mb4->un.varSLIConfig.be.embedded))); 3976 3977 hba->flag |= FC_MBOX_TIMEOUT; 3978 EMLXS_STATE_CHANGE(hba, FC_ERROR); 3979 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3980 3981 } else { 3982 if (mb->mbxCommand != MBX_DOWN_LOAD 3983 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 3984 EMLXS_MSGF(EMLXS_CONTEXT, 3985 &emlxs_mbox_detail_msg, 3986 "Completed. %s: mb=%p status=%x rc=%x" 3987 " Poll. embedded %d", 3988 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3989 rc, mb->mbxStatus, 3990 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 3991 (mb4->un.varSLIConfig.be.embedded))); 3992 } 3993 3994 /* Process the result */ 3995 if (!(mbq->flag & MBQ_PASSTHRU)) { 3996 if (mbq->mbox_cmpl) { 3997 (void) (mbq->mbox_cmpl)(hba, mbq); 3998 } 3999 } 4000 4001 emlxs_mb_fini(hba, NULL, mb->mbxStatus); 4002 } 4003 4004 mp = (MATCHMAP *)mbq->nonembed; 4005 if (mp) { 4006 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 4007 if (hdr_rsp->status) { 4008 EMLXS_MSGF(EMLXS_CONTEXT, 4009 &emlxs_mbox_detail_msg, 4010 "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", 4011 emlxs_mb_cmd_xlate(mb->mbxCommand), 4012 hdr_rsp->status, hdr_rsp->extra_status); 4013 4014 mb->mbxStatus = MBX_NONEMBED_ERROR; 4015 } 4016 } 4017 rc = mb->mbxStatus; 4018 4019 /* Attempt to send pending mailboxes */ 4020 mbq = (MAILBOXQ *)emlxs_mb_get(hba); 4021 if (mbq) { 4022 /* Attempt to send pending mailboxes */ 4023 i = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 4024 if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) { 4025 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4026 } 4027 } 4028 break; 4029 4030 case MBX_SLEEP: 4031 if (mb->mbxCommand != MBX_DOWN_LOAD 4032 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 4033 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 4034 "Sending. %s: mb=%p Sleep. embedded %d", 4035 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 4036 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 4037 (mb4->un.varSLIConfig.be.embedded))); 4038 } 4039 4040 iptr = hba->sli.sli4.mq.addr.virt; 4041 iptr += (hba->sli.sli4.mq.host_index * MAILBOX_CMD_SLI4_WSIZE); 4042 hba->sli.sli4.mq.host_index++; 4043 if (hba->sli.sli4.mq.host_index >= hba->sli.sli4.mq.max_index) { 4044 hba->sli.sli4.mq.host_index = 0; 4045 } 4046 4047 rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local); 4048 4049 if (rc != MBX_SUCCESS) { 4050 break; 4051 } 4052 4053 /* Wait for completion */ 4054 /* The driver clock is timing the mailbox. */ 4055 4056 mutex_enter(&EMLXS_MBOX_LOCK); 4057 while (!(mbq->flag & MBQ_COMPLETED)) { 4058 cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK); 4059 } 4060 mutex_exit(&EMLXS_MBOX_LOCK); 4061 4062 mp = (MATCHMAP *)mbq->nonembed; 4063 if (mp) { 4064 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 4065 if (hdr_rsp->status) { 4066 EMLXS_MSGF(EMLXS_CONTEXT, 4067 &emlxs_mbox_detail_msg, 4068 "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", 4069 emlxs_mb_cmd_xlate(mb->mbxCommand), 4070 hdr_rsp->status, hdr_rsp->extra_status); 4071 4072 mb->mbxStatus = MBX_NONEMBED_ERROR; 4073 } 4074 } 4075 rc = mb->mbxStatus; 4076 4077 if (rc == MBX_TIMEOUT) { 4078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 4079 "Timeout. %s: mb=%p tmo=%x Sleep. embedded %d", 4080 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo, 4081 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 4082 (mb4->un.varSLIConfig.be.embedded))); 4083 } else { 4084 if (mb->mbxCommand != MBX_DOWN_LOAD 4085 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 4086 EMLXS_MSGF(EMLXS_CONTEXT, 4087 &emlxs_mbox_detail_msg, 4088 "Completed. %s: mb=%p status=%x Sleep. " 4089 "embedded %d", 4090 emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc, 4091 ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : 4092 (mb4->un.varSLIConfig.be.embedded))); 4093 } 4094 } 4095 break; 4096 } 4097 4098 return (rc); 4099 4100 } /* emlxs_sli4_issue_mbox_cmd() */ 4101 4102 4103 4104 /*ARGSUSED*/ 4105 static uint32_t 4106 emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, 4107 uint32_t tmo) 4108 { 4109 emlxs_port_t *port = &PPORT; 4110 MAILBOX *mb; 4111 mbox_rsp_hdr_t *hdr_rsp; 4112 MATCHMAP *mp; 4113 uint32_t rc; 4114 uint32_t tmo_local; 4115 4116 mb = (MAILBOX *)mbq; 4117 4118 mb->mbxStatus = MBX_SUCCESS; 4119 rc = MBX_SUCCESS; 4120 4121 if (tmo < 30) { 4122 tmo = 30; 4123 } 4124 4125 /* Convert tmo seconds to 10 millisecond tics */ 4126 tmo_local = tmo * 100; 4127 4128 flag = MBX_POLL; 4129 4130 /* Check for hardware error */ 4131 if (hba->flag & FC_HARDWARE_ERROR) { 4132 mb->mbxStatus = MBX_HARDWARE_ERROR; 4133 return (MBX_HARDWARE_ERROR); 4134 } 4135 4136 /* Initialize mailbox area */ 4137 emlxs_mb_init(hba, mbq, flag, tmo); 4138 4139 switch (flag) { 4140 4141 case MBX_POLL: 4142 4143 rc = emlxs_sli4_issue_bootstrap(hba, mb, tmo_local); 4144 4145 /* Clean up the mailbox area */ 4146 if (rc == MBX_TIMEOUT) { 4147 hba->flag |= FC_MBOX_TIMEOUT; 4148 EMLXS_STATE_CHANGE(hba, FC_ERROR); 4149 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 4150 4151 } else { 4152 /* Process the result */ 4153 if (!(mbq->flag & MBQ_PASSTHRU)) { 4154 if (mbq->mbox_cmpl) { 4155 (void) (mbq->mbox_cmpl)(hba, mbq); 4156 } 4157 } 4158 4159 emlxs_mb_fini(hba, NULL, mb->mbxStatus); 4160 } 4161 4162 mp = (MATCHMAP *)mbq->nonembed; 4163 if (mp) { 4164 hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; 4165 if (hdr_rsp->status) { 4166 EMLXS_MSGF(EMLXS_CONTEXT, 4167 &emlxs_mbox_detail_msg, 4168 "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", 4169 emlxs_mb_cmd_xlate(mb->mbxCommand), 4170 hdr_rsp->status, hdr_rsp->extra_status); 4171 4172 mb->mbxStatus = MBX_NONEMBED_ERROR; 4173 } 4174 } 4175 rc = mb->mbxStatus; 4176 4177 break; 4178 } 4179 4180 return (rc); 4181 4182 } /* emlxs_sli4_issue_mbox_cmd4quiesce() */ 4183 4184 4185 4186 #ifdef SFCT_SUPPORT 4187 /*ARGSUSED*/ 4188 extern uint32_t 4189 emlxs_sli4_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, int channel) 4190 { 4191 emlxs_hba_t *hba = HBA; 4192 emlxs_config_t *cfg = &CFG; 4193 fct_cmd_t *fct_cmd; 4194 stmf_data_buf_t *dbuf; 4195 scsi_task_t *fct_task; 4196 fc_packet_t *pkt; 4197 CHANNEL *cp; 4198 XRIobj_t *xrip; 4199 emlxs_node_t *ndlp; 4200 IOCBQ *iocbq; 4201 IOCB *iocb; 4202 emlxs_wqe_t *wqe; 4203 ULP_SGE64 stage_sge; 4204 ULP_SGE64 *sge; 4205 RPIobj_t *rpip; 4206 int32_t sge_size; 4207 uint64_t sge_addr; 4208 uint32_t did; 4209 uint32_t timeout; 4210 4211 ddi_dma_cookie_t *cp_cmd; 4212 4213 pkt = PRIV2PKT(cmd_sbp); 4214 4215 cp = (CHANNEL *)cmd_sbp->channel; 4216 4217 iocbq = &cmd_sbp->iocbq; 4218 iocb = &iocbq->iocb; 4219 4220 did = cmd_sbp->did; 4221 if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) { 4222 4223 ndlp = cmd_sbp->node; 4224 rpip = EMLXS_NODE_TO_RPI(port, ndlp); 4225 4226 if (!rpip) { 4227 /* Use the fabric rpi */ 4228 rpip = port->vpip->fabric_rpip; 4229 } 4230 4231 /* Next allocate an Exchange for this command */ 4232 xrip = emlxs_sli4_alloc_xri(port, cmd_sbp, rpip, 4233 EMLXS_XRI_SOL_BLS_TYPE); 4234 4235 if (!xrip) { 4236 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4237 "Adapter Busy. Unable to allocate exchange. " 4238 "did=0x%x", did); 4239 4240 return (FC_TRAN_BUSY); 4241 } 4242 4243 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4244 "FCT Abort Request: xri=%d iotag=%d sbp=%p rxid=%x", 4245 xrip->XRI, xrip->iotag, cmd_sbp, pkt->pkt_cmd_fhdr.rx_id); 4246 4247 cmd_sbp->xrip = xrip; 4248 4249 cp->ulpSendCmd++; 4250 4251 /* Initalize iocbq */ 4252 iocbq->port = (void *)port; 4253 iocbq->node = (void *)ndlp; 4254 iocbq->channel = (void *)cp; 4255 4256 /* 4257 * Don't give the abort priority, we want the IOCB 4258 * we are aborting to be processed first. 4259 */ 4260 iocbq->flag |= IOCB_SPECIAL; 4261 4262 wqe = &iocbq->wqe; 4263 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 4264 4265 wqe = &iocbq->wqe; 4266 wqe->un.Abort.Criteria = ABORT_XRI_TAG; 4267 wqe->RequestTag = xrip->iotag; 4268 wqe->AbortTag = pkt->pkt_cmd_fhdr.rx_id; 4269 wqe->Command = CMD_ABORT_XRI_CX; 4270 wqe->Class = CLASS3; 4271 wqe->CQId = 0xffff; 4272 wqe->CmdType = WQE_TYPE_ABORT; 4273 4274 if (hba->state >= FC_LINK_UP) { 4275 wqe->un.Abort.IA = 0; 4276 } else { 4277 wqe->un.Abort.IA = 1; 4278 } 4279 4280 /* Set the pkt timer */ 4281 cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 4282 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 4283 4284 return (IOERR_SUCCESS); 4285 4286 } else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) { 4287 4288 timeout = pkt->pkt_timeout; 4289 ndlp = cmd_sbp->node; 4290 if (!ndlp) { 4291 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4292 "Unable to find rpi. did=0x%x", did); 4293 4294 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT, 4295 IOERR_INVALID_RPI, 0); 4296 return (0xff); 4297 } 4298 4299 cp->ulpSendCmd++; 4300 4301 /* Initalize iocbq */ 4302 iocbq->port = (void *)port; 4303 iocbq->node = (void *)ndlp; 4304 iocbq->channel = (void *)cp; 4305 4306 wqe = &iocbq->wqe; 4307 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 4308 4309 xrip = emlxs_sli4_register_xri(port, cmd_sbp, 4310 pkt->pkt_cmd_fhdr.rx_id, did); 4311 4312 if (!xrip) { 4313 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4314 "Unable to register xri %x. did=0x%x", 4315 pkt->pkt_cmd_fhdr.rx_id, did); 4316 4317 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT, 4318 IOERR_NO_XRI, 0); 4319 return (0xff); 4320 } 4321 4322 cmd_sbp->iotag = xrip->iotag; 4323 cmd_sbp->channel = cp; 4324 4325 #if (EMLXS_MODREV >= EMLXS_MODREV3) 4326 cp_cmd = pkt->pkt_cmd_cookie; 4327 #else 4328 cp_cmd = &pkt->pkt_cmd_cookie; 4329 #endif /* >= EMLXS_MODREV3 */ 4330 4331 sge_size = pkt->pkt_cmdlen; 4332 /* Make size a multiple of 4 */ 4333 if (sge_size & 3) { 4334 sge_size = (sge_size + 3) & 0xfffffffc; 4335 } 4336 sge_addr = cp_cmd->dmac_laddress; 4337 sge = xrip->SGList->virt; 4338 4339 stage_sge.addrHigh = PADDR_HI(sge_addr); 4340 stage_sge.addrLow = PADDR_LO(sge_addr); 4341 stage_sge.length = sge_size; 4342 stage_sge.offset = 0; 4343 stage_sge.type = 0; 4344 stage_sge.last = 1; 4345 4346 /* Copy staged SGE into SGL */ 4347 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, 4348 (uint8_t *)sge, sizeof (ULP_SGE64)); 4349 4350 /* Words 0-3 */ 4351 wqe->un.FcpCmd.Payload.addrHigh = stage_sge.addrHigh; 4352 wqe->un.FcpCmd.Payload.addrLow = stage_sge.addrLow; 4353 wqe->un.FcpCmd.Payload.tus.f.bdeSize = sge_size; 4354 wqe->un.FcpCmd.PayloadLength = sge_size; 4355 4356 /* Word 6 */ 4357 wqe->ContextTag = ndlp->nlp_Rpi; 4358 wqe->XRITag = xrip->XRI; 4359 4360 /* Word 7 */ 4361 wqe->Command = iocb->ULPCOMMAND; 4362 wqe->Class = cmd_sbp->class; 4363 wqe->ContextType = WQE_RPI_CONTEXT; 4364 wqe->Timer = ((timeout > 0xff) ? 0 : timeout); 4365 4366 /* Word 8 */ 4367 wqe->AbortTag = 0; 4368 4369 /* Word 9 */ 4370 wqe->RequestTag = xrip->iotag; 4371 wqe->OXId = (uint16_t)xrip->rx_id; 4372 4373 /* Word 10 */ 4374 if (xrip->flag & EMLXS_XRI_BUSY) { 4375 wqe->XC = 1; 4376 } 4377 4378 if (!(hba->sli.sli4.param.PHWQ)) { 4379 wqe->QOSd = 1; 4380 wqe->DBDE = 1; /* Data type for BDE 0 */ 4381 } 4382 4383 /* Word 11 */ 4384 wqe->CmdType = WQE_TYPE_TRSP; 4385 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 4386 4387 /* Set the pkt timer */ 4388 cmd_sbp->ticks = hba->timer_tics + timeout + 4389 ((timeout > 0xff) ? 0 : 10); 4390 4391 if (pkt->pkt_cmdlen) { 4392 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 4393 DDI_DMA_SYNC_FORDEV); 4394 } 4395 4396 return (IOERR_SUCCESS); 4397 } 4398 4399 fct_cmd = cmd_sbp->fct_cmd; 4400 did = fct_cmd->cmd_rportid; 4401 dbuf = cmd_sbp->fct_buf; 4402 fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 4403 ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 4404 if (!ndlp) { 4405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4406 "Unable to find rpi. did=0x%x", did); 4407 4408 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT, 4409 IOERR_INVALID_RPI, 0); 4410 return (0xff); 4411 } 4412 4413 4414 /* Initalize iocbq */ 4415 iocbq->port = (void *) port; 4416 iocbq->node = (void *)ndlp; 4417 iocbq->channel = (void *) cp; 4418 4419 wqe = &iocbq->wqe; 4420 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 4421 4422 xrip = cmd_sbp->xrip; 4423 if (!xrip) { 4424 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4425 "Unable to find xri. did=0x%x", did); 4426 4427 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT, 4428 IOERR_NO_XRI, 0); 4429 return (0xff); 4430 } 4431 4432 if (emlxs_sli4_register_xri(port, cmd_sbp, 4433 xrip->XRI, ndlp->nlp_DID) == NULL) { 4434 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4435 "Unable to register xri. did=0x%x", did); 4436 4437 emlxs_set_pkt_state(cmd_sbp, IOSTAT_LOCAL_REJECT, 4438 IOERR_NO_XRI, 0); 4439 return (0xff); 4440 } 4441 cmd_sbp->iotag = xrip->iotag; 4442 cmd_sbp->channel = cp; 4443 4444 if (cfg[CFG_TIMEOUT_ENABLE].current) { 4445 timeout = 4446 ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov); 4447 } else { 4448 timeout = 0x80000000; 4449 } 4450 cmd_sbp->ticks = 4451 hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10); 4452 4453 4454 iocb->ULPCT = 0; 4455 if (fct_task->task_flags & TF_WRITE_DATA) { 4456 iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX; 4457 wqe->CmdType = WQE_TYPE_TRECEIVE; /* Word 11 */ 4458 4459 } else { /* TF_READ_DATA */ 4460 4461 iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX; 4462 wqe->CmdType = WQE_TYPE_TSEND; /* Word 11 */ 4463 4464 if ((dbuf->db_data_size >= 4465 fct_task->task_expected_xfer_length)) { 4466 /* enable auto-rsp AP feature */ 4467 wqe->AR = 0x1; 4468 iocb->ULPCT = 0x1; /* for cmpl */ 4469 } 4470 } 4471 4472 (void) emlxs_sli4_fct_bde_setup(port, cmd_sbp); 4473 4474 /* Word 6 */ 4475 wqe->ContextTag = ndlp->nlp_Rpi; 4476 wqe->XRITag = xrip->XRI; 4477 4478 /* Word 7 */ 4479 wqe->Command = iocb->ULPCOMMAND; 4480 wqe->Class = cmd_sbp->class; 4481 wqe->ContextType = WQE_RPI_CONTEXT; 4482 wqe->Timer = ((timeout > 0xff) ? 0 : timeout); 4483 wqe->PU = 1; 4484 4485 /* Word 8 */ 4486 wqe->AbortTag = 0; 4487 4488 /* Word 9 */ 4489 wqe->RequestTag = xrip->iotag; 4490 wqe->OXId = (uint16_t)fct_cmd->cmd_oxid; 4491 4492 /* Word 10 */ 4493 if (xrip->flag & EMLXS_XRI_BUSY) { 4494 wqe->XC = 1; 4495 } 4496 4497 if (!(hba->sli.sli4.param.PHWQ)) { 4498 wqe->QOSd = 1; 4499 wqe->DBDE = 1; /* Data type for BDE 0 */ 4500 } 4501 4502 /* Word 11 */ 4503 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 4504 4505 /* Word 12 */ 4506 wqe->CmdSpecific = dbuf->db_data_size; 4507 4508 return (IOERR_SUCCESS); 4509 4510 } /* emlxs_sli4_prep_fct_iocb() */ 4511 #endif /* SFCT_SUPPORT */ 4512 4513 4514 /*ARGSUSED*/ 4515 extern uint32_t 4516 emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) 4517 { 4518 emlxs_hba_t *hba = HBA; 4519 fc_packet_t *pkt; 4520 CHANNEL *cp; 4521 RPIobj_t *rpip; 4522 XRIobj_t *xrip; 4523 emlxs_wqe_t *wqe; 4524 IOCBQ *iocbq; 4525 IOCB *iocb; 4526 NODELIST *node; 4527 uint16_t iotag; 4528 uint32_t did; 4529 4530 pkt = PRIV2PKT(sbp); 4531 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 4532 cp = &hba->chan[channel]; 4533 4534 iocbq = &sbp->iocbq; 4535 iocbq->channel = (void *) cp; 4536 iocbq->port = (void *) port; 4537 4538 wqe = &iocbq->wqe; 4539 iocb = &iocbq->iocb; 4540 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 4541 bzero((void *)iocb, sizeof (IOCB)); 4542 4543 /* Find target node object */ 4544 node = (NODELIST *)iocbq->node; 4545 rpip = EMLXS_NODE_TO_RPI(port, node); 4546 4547 if (!rpip) { 4548 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4549 "Unable to find rpi. did=0x%x", did); 4550 4551 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 4552 IOERR_INVALID_RPI, 0); 4553 return (0xff); 4554 } 4555 4556 sbp->channel = cp; 4557 /* Next allocate an Exchange for this command */ 4558 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip, 4559 EMLXS_XRI_SOL_FCP_TYPE); 4560 4561 if (!xrip) { 4562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4563 "Adapter Busy. Unable to allocate exchange. did=0x%x", did); 4564 4565 return (FC_TRAN_BUSY); 4566 } 4567 sbp->bmp = NULL; 4568 iotag = sbp->iotag; 4569 4570 #ifdef DEBUG_FASTPATH 4571 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4572 "FCP: Prep xri=%d iotag=%d oxid=%x rpi=%d", 4573 xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI); 4574 #endif /* DEBUG_FASTPATH */ 4575 4576 /* Indicate this is a FCP cmd */ 4577 iocbq->flag |= IOCB_FCP_CMD; 4578 4579 if (emlxs_sli4_bde_setup(port, sbp)) { 4580 emlxs_sli4_free_xri(port, sbp, xrip, 1); 4581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4582 "Adapter Busy. Unable to setup SGE. did=0x%x", did); 4583 4584 return (FC_TRAN_BUSY); 4585 } 4586 4587 /* DEBUG */ 4588 #ifdef DEBUG_FCP 4589 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4590 "FCP: SGLaddr virt %p phys %p size %d", xrip->SGList->virt, 4591 xrip->SGList->phys, pkt->pkt_datalen); 4592 emlxs_data_dump(port, "FCP: SGL", 4593 (uint32_t *)xrip->SGList->virt, 32, 0); 4594 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4595 "FCP: CMD virt %p len %d:%d:%d", 4596 pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen); 4597 emlxs_data_dump(port, "FCP: CMD", (uint32_t *)pkt->pkt_cmd, 10, 0); 4598 #endif /* DEBUG_FCP */ 4599 4600 EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0, 4601 xrip->SGList->size, DDI_DMA_SYNC_FORDEV); 4602 4603 /* if device is FCP-2 device, set the following bit */ 4604 /* that says to run the FC-TAPE protocol. */ 4605 if (node->nlp_fcp_info & NLP_FCP_2_DEVICE) { 4606 wqe->ERP = 1; 4607 } 4608 4609 if (pkt->pkt_datalen == 0) { 4610 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR; 4611 wqe->Command = CMD_FCP_ICMND64_CR; 4612 wqe->CmdType = WQE_TYPE_FCP_DATA_IN; 4613 } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 4614 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR; 4615 wqe->Command = CMD_FCP_IREAD64_CR; 4616 wqe->CmdType = WQE_TYPE_FCP_DATA_IN; 4617 wqe->PU = PARM_XFER_CHECK; 4618 } else { 4619 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR; 4620 wqe->Command = CMD_FCP_IWRITE64_CR; 4621 wqe->CmdType = WQE_TYPE_FCP_DATA_OUT; 4622 } 4623 wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen; 4624 4625 if (!(hba->sli.sli4.param.PHWQ)) { 4626 wqe->DBDE = 1; /* Data type for BDE 0 */ 4627 } 4628 wqe->ContextTag = rpip->RPI; 4629 wqe->ContextType = WQE_RPI_CONTEXT; 4630 wqe->XRITag = xrip->XRI; 4631 wqe->Timer = 4632 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 4633 4634 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { 4635 wqe->CCPE = 1; 4636 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd; 4637 } 4638 4639 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 4640 case FC_TRAN_CLASS2: 4641 wqe->Class = CLASS2; 4642 break; 4643 case FC_TRAN_CLASS3: 4644 default: 4645 wqe->Class = CLASS3; 4646 break; 4647 } 4648 sbp->class = wqe->Class; 4649 wqe->RequestTag = iotag; 4650 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 4651 4652 return (FC_SUCCESS); 4653 } /* emlxs_sli4_prep_fcp_iocb() */ 4654 4655 4656 /*ARGSUSED*/ 4657 static uint32_t 4658 emlxs_sli4_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 4659 { 4660 return (FC_TRAN_BUSY); 4661 4662 } /* emlxs_sli4_prep_ip_iocb() */ 4663 4664 4665 /*ARGSUSED*/ 4666 static uint32_t 4667 emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 4668 { 4669 emlxs_hba_t *hba = HBA; 4670 fc_packet_t *pkt; 4671 IOCBQ *iocbq; 4672 IOCB *iocb; 4673 emlxs_wqe_t *wqe; 4674 FCFIobj_t *fcfp; 4675 RPIobj_t *reserved_rpip = NULL; 4676 RPIobj_t *rpip = NULL; 4677 XRIobj_t *xrip; 4678 CHANNEL *cp; 4679 uint32_t did; 4680 uint32_t cmd; 4681 ULP_SGE64 stage_sge; 4682 ULP_SGE64 *sge; 4683 ddi_dma_cookie_t *cp_cmd; 4684 ddi_dma_cookie_t *cp_resp; 4685 emlxs_node_t *node; 4686 4687 pkt = PRIV2PKT(sbp); 4688 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 4689 4690 iocbq = &sbp->iocbq; 4691 wqe = &iocbq->wqe; 4692 iocb = &iocbq->iocb; 4693 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 4694 bzero((void *)iocb, sizeof (IOCB)); 4695 cp = &hba->chan[hba->channel_els]; 4696 4697 /* Initalize iocbq */ 4698 iocbq->port = (void *) port; 4699 iocbq->channel = (void *) cp; 4700 4701 sbp->channel = cp; 4702 sbp->bmp = NULL; 4703 4704 #if (EMLXS_MODREV >= EMLXS_MODREV3) 4705 cp_cmd = pkt->pkt_cmd_cookie; 4706 cp_resp = pkt->pkt_resp_cookie; 4707 #else 4708 cp_cmd = &pkt->pkt_cmd_cookie; 4709 cp_resp = &pkt->pkt_resp_cookie; 4710 #endif /* >= EMLXS_MODREV3 */ 4711 4712 /* CMD payload */ 4713 sge = &stage_sge; 4714 sge->addrHigh = PADDR_HI(cp_cmd->dmac_laddress); 4715 sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress); 4716 sge->length = pkt->pkt_cmdlen; 4717 sge->offset = 0; 4718 sge->type = 0; 4719 4720 cmd = *((uint32_t *)pkt->pkt_cmd); 4721 cmd &= ELS_CMD_MASK; 4722 4723 /* Initalize iocb */ 4724 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 4725 /* ELS Response */ 4726 4727 sbp->xrip = 0; 4728 xrip = emlxs_sli4_register_xri(port, sbp, 4729 pkt->pkt_cmd_fhdr.rx_id, did); 4730 4731 if (!xrip) { 4732 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 4733 "Unable to find XRI. rxid=%x", 4734 pkt->pkt_cmd_fhdr.rx_id); 4735 4736 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 4737 IOERR_NO_XRI, 0); 4738 return (0xff); 4739 } 4740 4741 rpip = xrip->rpip; 4742 4743 if (!rpip) { 4744 /* This means that we had a node registered */ 4745 /* when the unsol request came in but the node */ 4746 /* has since been unregistered. */ 4747 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 4748 "Unable to find RPI. rxid=%x", 4749 pkt->pkt_cmd_fhdr.rx_id); 4750 4751 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 4752 IOERR_INVALID_RPI, 0); 4753 return (0xff); 4754 } 4755 4756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4757 "ELS: Prep xri=%d iotag=%d oxid=%x rpi=%d", 4758 xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI); 4759 4760 iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX; 4761 wqe->Command = CMD_XMIT_ELS_RSP64_CX; 4762 wqe->CmdType = WQE_TYPE_GEN; 4763 if (!(hba->sli.sli4.param.PHWQ)) { 4764 wqe->DBDE = 1; /* Data type for BDE 0 */ 4765 } 4766 4767 wqe->un.ElsRsp.Payload.addrHigh = sge->addrHigh; 4768 wqe->un.ElsRsp.Payload.addrLow = sge->addrLow; 4769 wqe->un.ElsRsp.Payload.tus.f.bdeSize = pkt->pkt_cmdlen; 4770 wqe->un.ElsCmd.PayloadLength = pkt->pkt_cmdlen; 4771 4772 wqe->un.ElsRsp.RemoteId = did; 4773 wqe->PU = 0x3; 4774 wqe->OXId = xrip->rx_id; 4775 4776 sge->last = 1; 4777 /* Now sge is fully staged */ 4778 4779 sge = xrip->SGList->virt; 4780 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, 4781 sizeof (ULP_SGE64)); 4782 4783 if (rpip->RPI == FABRIC_RPI) { 4784 wqe->ContextTag = port->vpip->VPI; 4785 wqe->ContextType = WQE_VPI_CONTEXT; 4786 } else { 4787 wqe->ContextTag = rpip->RPI; 4788 wqe->ContextType = WQE_RPI_CONTEXT; 4789 } 4790 4791 if ((cmd == ELS_CMD_ACC) && (sbp->ucmd == ELS_CMD_FLOGI)) { 4792 wqe->un.ElsCmd.SP = 1; 4793 wqe->un.ElsCmd.LocalId = 0xFFFFFE; 4794 } 4795 4796 } else { 4797 /* ELS Request */ 4798 4799 fcfp = port->vpip->vfip->fcfp; 4800 node = (emlxs_node_t *)iocbq->node; 4801 rpip = EMLXS_NODE_TO_RPI(port, node); 4802 4803 if (!rpip) { 4804 /* Use the fabric rpi */ 4805 rpip = port->vpip->fabric_rpip; 4806 } 4807 4808 /* Next allocate an Exchange for this command */ 4809 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip, 4810 EMLXS_XRI_SOL_ELS_TYPE); 4811 4812 if (!xrip) { 4813 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 4814 "Adapter Busy. Unable to allocate exchange. " 4815 "did=0x%x", did); 4816 4817 return (FC_TRAN_BUSY); 4818 } 4819 4820 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4821 "ELS: Prep xri=%d iotag=%d rpi=%d", 4822 xrip->XRI, xrip->iotag, rpip->RPI); 4823 4824 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR; 4825 wqe->Command = CMD_ELS_REQUEST64_CR; 4826 wqe->CmdType = WQE_TYPE_ELS; 4827 if (!(hba->sli.sli4.param.PHWQ)) { 4828 wqe->DBDE = 1; /* Data type for BDE 0 */ 4829 } 4830 4831 wqe->un.ElsCmd.Payload.addrHigh = sge->addrHigh; 4832 wqe->un.ElsCmd.Payload.addrLow = sge->addrLow; 4833 wqe->un.ElsCmd.Payload.tus.f.bdeSize = pkt->pkt_cmdlen; 4834 4835 wqe->un.ElsCmd.RemoteId = did; 4836 wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 4837 4838 /* setup for rsp */ 4839 iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did; 4840 iocb->ULPPU = 1; /* Wd4 is relative offset */ 4841 4842 sge->last = 0; 4843 4844 sge = xrip->SGList->virt; 4845 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, 4846 sizeof (ULP_SGE64)); 4847 4848 wqe->un.ElsCmd.PayloadLength = 4849 pkt->pkt_cmdlen; /* Byte offset of rsp data */ 4850 4851 /* RSP payload */ 4852 sge = &stage_sge; 4853 sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress); 4854 sge->addrLow = PADDR_LO(cp_resp->dmac_laddress); 4855 sge->length = pkt->pkt_rsplen; 4856 sge->offset = 0; 4857 sge->last = 1; 4858 /* Now sge is fully staged */ 4859 4860 sge = xrip->SGList->virt; 4861 sge++; 4862 BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, 4863 sizeof (ULP_SGE64)); 4864 #ifdef DEBUG_ELS 4865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4866 "ELS: SGLaddr virt %p phys %p", 4867 xrip->SGList->virt, xrip->SGList->phys); 4868 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4869 "ELS: PAYLOAD virt %p phys %p", 4870 pkt->pkt_cmd, cp_cmd->dmac_laddress); 4871 emlxs_data_dump(port, "ELS: SGL", 4872 (uint32_t *)xrip->SGList->virt, 12, 0); 4873 #endif /* DEBUG_ELS */ 4874 4875 switch (cmd) { 4876 case ELS_CMD_FLOGI: 4877 wqe->un.ElsCmd.SP = 1; 4878 4879 if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) == 4880 SLI_INTF_IF_TYPE_0) { 4881 wqe->ContextTag = fcfp->FCFI; 4882 wqe->ContextType = WQE_FCFI_CONTEXT; 4883 } else { 4884 wqe->ContextTag = port->vpip->VPI; 4885 wqe->ContextType = WQE_VPI_CONTEXT; 4886 } 4887 4888 if (hba->flag & FC_FIP_SUPPORTED) { 4889 wqe->CmdType |= WQE_TYPE_MASK_FIP; 4890 } 4891 4892 if (hba->topology == TOPOLOGY_LOOP) { 4893 wqe->un.ElsCmd.LocalId = port->did; 4894 } 4895 4896 wqe->ELSId = WQE_ELSID_FLOGI; 4897 break; 4898 case ELS_CMD_FDISC: 4899 wqe->un.ElsCmd.SP = 1; 4900 wqe->ContextTag = port->vpip->VPI; 4901 wqe->ContextType = WQE_VPI_CONTEXT; 4902 4903 if (hba->flag & FC_FIP_SUPPORTED) { 4904 wqe->CmdType |= WQE_TYPE_MASK_FIP; 4905 } 4906 4907 wqe->ELSId = WQE_ELSID_FDISC; 4908 break; 4909 case ELS_CMD_LOGO: 4910 if ((did == FABRIC_DID) && 4911 (hba->flag & FC_FIP_SUPPORTED)) { 4912 wqe->CmdType |= WQE_TYPE_MASK_FIP; 4913 } 4914 4915 wqe->ContextTag = port->vpip->VPI; 4916 wqe->ContextType = WQE_VPI_CONTEXT; 4917 wqe->ELSId = WQE_ELSID_LOGO; 4918 break; 4919 case ELS_CMD_PLOGI: 4920 if (rpip->RPI == FABRIC_RPI) { 4921 if (hba->flag & FC_PT_TO_PT) { 4922 wqe->un.ElsCmd.SP = 1; 4923 wqe->un.ElsCmd.LocalId = port->did; 4924 } 4925 4926 wqe->ContextTag = port->vpip->VPI; 4927 wqe->ContextType = WQE_VPI_CONTEXT; 4928 } else { 4929 wqe->ContextTag = rpip->RPI; 4930 wqe->ContextType = WQE_RPI_CONTEXT; 4931 } 4932 4933 wqe->ELSId = WQE_ELSID_PLOGI; 4934 break; 4935 default: 4936 if (rpip->RPI == FABRIC_RPI) { 4937 wqe->ContextTag = port->vpip->VPI; 4938 wqe->ContextType = WQE_VPI_CONTEXT; 4939 } else { 4940 wqe->ContextTag = rpip->RPI; 4941 wqe->ContextType = WQE_RPI_CONTEXT; 4942 } 4943 4944 wqe->ELSId = WQE_ELSID_CMD; 4945 break; 4946 } 4947 4948 #ifdef SFCT_SUPPORT 4949 /* This allows fct to abort the request */ 4950 if (sbp->fct_cmd) { 4951 sbp->fct_cmd->cmd_oxid = xrip->XRI; 4952 sbp->fct_cmd->cmd_rxid = 0xFFFF; 4953 } 4954 #endif /* SFCT_SUPPORT */ 4955 } 4956 4957 if (wqe->ContextType == WQE_VPI_CONTEXT) { 4958 reserved_rpip = emlxs_rpi_reserve_notify(port, did, xrip); 4959 4960 if (!reserved_rpip) { 4961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 4962 "Unable to alloc reserved RPI. rxid=%x. Rejecting.", 4963 pkt->pkt_cmd_fhdr.rx_id); 4964 4965 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 4966 IOERR_INVALID_RPI, 0); 4967 return (0xff); 4968 } 4969 4970 /* Store the reserved rpi */ 4971 if (wqe->Command == CMD_ELS_REQUEST64_CR) { 4972 wqe->OXId = reserved_rpip->RPI; 4973 } else { 4974 wqe->CmdSpecific = reserved_rpip->RPI; 4975 } 4976 } 4977 4978 EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0, 4979 xrip->SGList->size, DDI_DMA_SYNC_FORDEV); 4980 4981 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { 4982 wqe->CCPE = 1; 4983 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd; 4984 } 4985 4986 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 4987 case FC_TRAN_CLASS2: 4988 wqe->Class = CLASS2; 4989 break; 4990 case FC_TRAN_CLASS3: 4991 default: 4992 wqe->Class = CLASS3; 4993 break; 4994 } 4995 sbp->class = wqe->Class; 4996 wqe->XRITag = xrip->XRI; 4997 wqe->RequestTag = xrip->iotag; 4998 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 4999 return (FC_SUCCESS); 5000 5001 } /* emlxs_sli4_prep_els_iocb() */ 5002 5003 5004 /*ARGSUSED*/ 5005 static uint32_t 5006 emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 5007 { 5008 emlxs_hba_t *hba = HBA; 5009 fc_packet_t *pkt; 5010 IOCBQ *iocbq; 5011 IOCB *iocb; 5012 emlxs_wqe_t *wqe; 5013 NODELIST *node = NULL; 5014 CHANNEL *cp; 5015 RPIobj_t *rpip; 5016 XRIobj_t *xrip; 5017 uint32_t did; 5018 5019 pkt = PRIV2PKT(sbp); 5020 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 5021 5022 iocbq = &sbp->iocbq; 5023 wqe = &iocbq->wqe; 5024 iocb = &iocbq->iocb; 5025 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 5026 bzero((void *)iocb, sizeof (IOCB)); 5027 5028 cp = &hba->chan[hba->channel_ct]; 5029 5030 iocbq->port = (void *) port; 5031 iocbq->channel = (void *) cp; 5032 5033 sbp->bmp = NULL; 5034 sbp->channel = cp; 5035 5036 /* Initalize wqe */ 5037 if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 5038 /* CT Response */ 5039 5040 sbp->xrip = 0; 5041 xrip = emlxs_sli4_register_xri(port, sbp, 5042 pkt->pkt_cmd_fhdr.rx_id, did); 5043 5044 if (!xrip) { 5045 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 5046 "Unable to find XRI. rxid=%x", 5047 pkt->pkt_cmd_fhdr.rx_id); 5048 5049 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 5050 IOERR_NO_XRI, 0); 5051 return (0xff); 5052 } 5053 5054 rpip = xrip->rpip; 5055 5056 if (!rpip) { 5057 /* This means that we had a node registered */ 5058 /* when the unsol request came in but the node */ 5059 /* has since been unregistered. */ 5060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 5061 "Unable to find RPI. rxid=%x", 5062 pkt->pkt_cmd_fhdr.rx_id); 5063 5064 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 5065 IOERR_INVALID_RPI, 0); 5066 return (0xff); 5067 } 5068 5069 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5070 "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d", 5071 xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI); 5072 5073 if (emlxs_sli4_bde_setup(port, sbp)) { 5074 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 5075 "Adapter Busy. Unable to setup SGE. did=0x%x", did); 5076 5077 return (FC_TRAN_BUSY); 5078 } 5079 5080 if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) { 5081 wqe->un.XmitSeq.Rsvd0 = 0; /* Word3 now reserved */ 5082 } 5083 5084 if (!(hba->sli.sli4.param.PHWQ)) { 5085 wqe->DBDE = 1; /* Data type for BDE 0 */ 5086 } 5087 5088 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CR; 5089 wqe->CmdType = WQE_TYPE_GEN; 5090 wqe->Command = CMD_XMIT_SEQUENCE64_CR; 5091 wqe->LenLoc = 2; 5092 5093 if (((SLI_CT_REQUEST *) pkt->pkt_cmd)->CommandResponse.bits. 5094 CmdRsp == (LE_SWAP16(SLI_CT_LOOPBACK))) { 5095 wqe->un.XmitSeq.xo = 1; 5096 } else { 5097 wqe->un.XmitSeq.xo = 0; 5098 } 5099 5100 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) { 5101 wqe->un.XmitSeq.ls = 1; 5102 } 5103 5104 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 5105 wqe->un.XmitSeq.si = 1; 5106 } 5107 5108 wqe->un.XmitSeq.DFctl = pkt->pkt_cmd_fhdr.df_ctl; 5109 wqe->un.XmitSeq.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 5110 wqe->un.XmitSeq.Type = pkt->pkt_cmd_fhdr.type; 5111 wqe->OXId = xrip->rx_id; 5112 wqe->XC = 0; /* xri_tag is a new exchange */ 5113 wqe->CmdSpecific = wqe->un.GenReq.Payload.tus.f.bdeSize; 5114 5115 } else { 5116 /* CT Request */ 5117 5118 node = (emlxs_node_t *)iocbq->node; 5119 rpip = EMLXS_NODE_TO_RPI(port, node); 5120 5121 if (!rpip) { 5122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 5123 "Unable to find rpi. did=0x%x rpi=%d", 5124 did, node->nlp_Rpi); 5125 5126 emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 5127 IOERR_INVALID_RPI, 0); 5128 return (0xff); 5129 } 5130 5131 /* Next allocate an Exchange for this command */ 5132 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip, 5133 EMLXS_XRI_SOL_CT_TYPE); 5134 5135 if (!xrip) { 5136 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 5137 "Adapter Busy. Unable to allocate exchange. " 5138 "did=0x%x", did); 5139 5140 return (FC_TRAN_BUSY); 5141 } 5142 5143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5144 "CT: Prep xri=%d iotag=%d oxid=%x rpi=%d", 5145 xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI); 5146 5147 if (emlxs_sli4_bde_setup(port, sbp)) { 5148 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 5149 "Adapter Busy. Unable to setup SGE. did=0x%x", did); 5150 5151 emlxs_sli4_free_xri(port, sbp, xrip, 1); 5152 return (FC_TRAN_BUSY); 5153 } 5154 5155 if (!(hba->sli.sli4.param.PHWQ)) { 5156 wqe->DBDE = 1; /* Data type for BDE 0 */ 5157 } 5158 5159 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR; 5160 wqe->CmdType = WQE_TYPE_GEN; 5161 wqe->Command = CMD_GEN_REQUEST64_CR; 5162 wqe->un.GenReq.la = 1; 5163 wqe->un.GenReq.DFctl = pkt->pkt_cmd_fhdr.df_ctl; 5164 wqe->un.GenReq.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 5165 wqe->un.GenReq.Type = pkt->pkt_cmd_fhdr.type; 5166 5167 #ifdef DEBUG_CT 5168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5169 "CT: SGLaddr virt %p phys %p", xrip->SGList->virt, 5170 xrip->SGList->phys); 5171 emlxs_data_dump(port, "CT: SGL", (uint32_t *)xrip->SGList->virt, 5172 12, 0); 5173 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5174 "CT: CMD virt %p len %d:%d", 5175 pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen); 5176 emlxs_data_dump(port, "CT: DATA", (uint32_t *)pkt->pkt_cmd, 5177 20, 0); 5178 #endif /* DEBUG_CT */ 5179 5180 #ifdef SFCT_SUPPORT 5181 /* This allows fct to abort the request */ 5182 if (sbp->fct_cmd) { 5183 sbp->fct_cmd->cmd_oxid = xrip->XRI; 5184 sbp->fct_cmd->cmd_rxid = 0xFFFF; 5185 } 5186 #endif /* SFCT_SUPPORT */ 5187 } 5188 5189 /* Setup for rsp */ 5190 iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 5191 iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 5192 iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 5193 iocb->ULPPU = 1; /* Wd4 is relative offset */ 5194 5195 EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0, 5196 xrip->SGList->size, DDI_DMA_SYNC_FORDEV); 5197 5198 wqe->ContextTag = rpip->RPI; 5199 wqe->ContextType = WQE_RPI_CONTEXT; 5200 wqe->XRITag = xrip->XRI; 5201 wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 5202 5203 if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { 5204 wqe->CCPE = 1; 5205 wqe->CCP = pkt->pkt_cmd_fhdr.rsvd; 5206 } 5207 5208 switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 5209 case FC_TRAN_CLASS2: 5210 wqe->Class = CLASS2; 5211 break; 5212 case FC_TRAN_CLASS3: 5213 default: 5214 wqe->Class = CLASS3; 5215 break; 5216 } 5217 sbp->class = wqe->Class; 5218 wqe->RequestTag = xrip->iotag; 5219 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 5220 return (FC_SUCCESS); 5221 5222 } /* emlxs_sli4_prep_ct_iocb() */ 5223 5224 5225 /*ARGSUSED*/ 5226 static int 5227 emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) 5228 { 5229 uint32_t *ptr; 5230 EQE_u eqe; 5231 int rc = 0; 5232 off_t offset; 5233 5234 mutex_enter(&EMLXS_PORT_LOCK); 5235 5236 ptr = eq->addr.virt; 5237 ptr += eq->host_index; 5238 5239 offset = (off_t)((uint64_t)((unsigned long) 5240 eq->addr.virt) - 5241 (uint64_t)((unsigned long) 5242 hba->sli.sli4.slim2.virt)); 5243 5244 EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset, 5245 4096, DDI_DMA_SYNC_FORKERNEL); 5246 5247 eqe.word = *ptr; 5248 eqe.word = BE_SWAP32(eqe.word); 5249 5250 if ((eqe.word & EQE_VALID) == eq->qe_valid) { 5251 rc = 1; 5252 } 5253 5254 mutex_exit(&EMLXS_PORT_LOCK); 5255 5256 return (rc); 5257 5258 } /* emlxs_sli4_read_eq */ 5259 5260 5261 static void 5262 emlxs_sli4_poll_intr(emlxs_hba_t *hba) 5263 { 5264 int rc = 0; 5265 int i; 5266 char arg[] = {0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}; 5267 5268 /* Check attention bits once and process if required */ 5269 5270 for (i = 0; i < hba->intr_count; i++) { 5271 rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[i]); 5272 if (rc == 1) { 5273 break; 5274 } 5275 } 5276 5277 if (rc != 1) { 5278 return; 5279 } 5280 5281 (void) emlxs_sli4_msi_intr((char *)hba, 5282 (char *)(unsigned long)arg[i]); 5283 5284 return; 5285 5286 } /* emlxs_sli4_poll_intr() */ 5287 5288 5289 /*ARGSUSED*/ 5290 static void 5291 emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe) 5292 { 5293 emlxs_port_t *port = &PPORT; 5294 uint8_t status; 5295 5296 /* Save the event tag */ 5297 if (hba->link_event_tag == cqe->un.link.event_tag) { 5298 HBASTATS.LinkMultiEvent++; 5299 } else if (hba->link_event_tag + 1 < cqe->un.link.event_tag) { 5300 HBASTATS.LinkMultiEvent++; 5301 } 5302 hba->link_event_tag = cqe->un.link.event_tag; 5303 5304 switch (cqe->event_code) { 5305 case ASYNC_EVENT_CODE_FCOE_LINK_STATE: 5306 HBASTATS.LinkEvent++; 5307 5308 switch (cqe->un.link.link_status) { 5309 case ASYNC_EVENT_PHYS_LINK_UP: 5310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5311 "Link Async Event: PHYS_LINK_UP. val=%d " 5312 "type=%x event=%x", 5313 cqe->valid, cqe->event_type, HBASTATS.LinkEvent); 5314 break; 5315 5316 case ASYNC_EVENT_LOGICAL_LINK_UP: 5317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5318 "Link Async Event: LOGICAL_LINK_UP. val=%d " 5319 "type=%x event=%x", 5320 cqe->valid, cqe->event_type, HBASTATS.LinkEvent); 5321 5322 emlxs_sli4_handle_fcoe_link_event(hba, cqe); 5323 break; 5324 5325 case ASYNC_EVENT_PHYS_LINK_DOWN: 5326 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5327 "Link Async Event: PHYS_LINK_DOWN. val=%d " 5328 "type=%x event=%x", 5329 cqe->valid, cqe->event_type, HBASTATS.LinkEvent); 5330 5331 emlxs_sli4_handle_fcoe_link_event(hba, cqe); 5332 break; 5333 5334 case ASYNC_EVENT_LOGICAL_LINK_DOWN: 5335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5336 "Link Async Event: LOGICAL_LINK_DOWN. val=%d " 5337 "type=%x event=%x", 5338 cqe->valid, cqe->event_type, HBASTATS.LinkEvent); 5339 5340 emlxs_sli4_handle_fcoe_link_event(hba, cqe); 5341 break; 5342 default: 5343 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5344 "Link Async Event: Unknown link status=%d event=%x", 5345 cqe->un.link.link_status, HBASTATS.LinkEvent); 5346 break; 5347 } 5348 break; 5349 case ASYNC_EVENT_CODE_FCOE_FIP: 5350 switch (cqe->un.fcoe.evt_type) { 5351 case ASYNC_EVENT_NEW_FCF_DISC: 5352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5353 "FIP Async Event: FCF_FOUND %d:%d", 5354 cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); 5355 5356 (void) emlxs_fcf_found_notify(port, 5357 cqe->un.fcoe.ref_index); 5358 break; 5359 case ASYNC_EVENT_FCF_TABLE_FULL: 5360 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5361 "FIP Async Event: FCFTAB_FULL %d:%d", 5362 cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); 5363 5364 (void) emlxs_fcf_full_notify(port); 5365 break; 5366 case ASYNC_EVENT_FCF_DEAD: 5367 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5368 "FIP Async Event: FCF_LOST %d:%d", 5369 cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); 5370 5371 (void) emlxs_fcf_lost_notify(port, 5372 cqe->un.fcoe.ref_index); 5373 break; 5374 case ASYNC_EVENT_VIRT_LINK_CLEAR: 5375 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5376 "FIP Async Event: CVL %d", 5377 cqe->un.fcoe.ref_index); 5378 5379 (void) emlxs_fcf_cvl_notify(port, 5380 emlxs_sli4_vpi_to_index(hba, 5381 cqe->un.fcoe.ref_index)); 5382 break; 5383 5384 case ASYNC_EVENT_FCF_MODIFIED: 5385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5386 "FIP Async Event: FCF_CHANGED %d", 5387 cqe->un.fcoe.ref_index); 5388 5389 (void) emlxs_fcf_changed_notify(port, 5390 cqe->un.fcoe.ref_index); 5391 break; 5392 default: 5393 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5394 "FIP Async Event: Unknown event type=%d", 5395 cqe->un.fcoe.evt_type); 5396 break; 5397 } 5398 break; 5399 case ASYNC_EVENT_CODE_DCBX: 5400 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5401 "DCBX Async Event: type=%d. Not supported.", 5402 cqe->event_type); 5403 break; 5404 case ASYNC_EVENT_CODE_GRP_5: 5405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5406 "Group 5 Async Event: type=%d.", cqe->event_type); 5407 if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) { 5408 hba->qos_linkspeed = cqe->un.qos.qos_link_speed; 5409 } 5410 break; 5411 case ASYNC_EVENT_CODE_FC_EVENT: 5412 switch (cqe->event_type) { 5413 case ASYNC_EVENT_FC_LINK_ATT: 5414 HBASTATS.LinkEvent++; 5415 5416 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5417 "FC Async Event: Link Attention. event=%x", 5418 HBASTATS.LinkEvent); 5419 5420 emlxs_sli4_handle_fc_link_att(hba, cqe); 5421 break; 5422 case ASYNC_EVENT_FC_SHARED_LINK_ATT: 5423 HBASTATS.LinkEvent++; 5424 5425 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5426 "FC Async Event: Shared Link Attention. event=%x", 5427 HBASTATS.LinkEvent); 5428 5429 emlxs_sli4_handle_fc_link_att(hba, cqe); 5430 break; 5431 default: 5432 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5433 "FC Async Event: Unknown event. type=%d event=%x", 5434 cqe->event_type, HBASTATS.LinkEvent); 5435 } 5436 break; 5437 case ASYNC_EVENT_CODE_PORT: 5438 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5439 "SLI Port Async Event: type=%d", cqe->event_type); 5440 5441 switch (cqe->event_type) { 5442 case ASYNC_EVENT_PORT_OTEMP: 5443 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5444 "SLI Port Async Event: Temperature limit exceeded"); 5445 cmn_err(CE_WARN, 5446 "^%s%d: Temperature limit exceeded. Fibre channel " 5447 "controller temperature %u degrees C", 5448 DRIVER_NAME, hba->ddiinst, 5449 BE_SWAP32(*(uint32_t *)cqe->un.port.link_status)); 5450 break; 5451 5452 case ASYNC_EVENT_PORT_NTEMP: 5453 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5454 "SLI Port Async Event: Temperature returned to " 5455 "normal"); 5456 cmn_err(CE_WARN, 5457 "^%s%d: Temperature returned to normal", 5458 DRIVER_NAME, hba->ddiinst); 5459 break; 5460 5461 case ASYNC_EVENT_MISCONFIG_PORT: 5462 *((uint32_t *)cqe->un.port.link_status) = 5463 BE_SWAP32(*((uint32_t *)cqe->un.port.link_status)); 5464 status = 5465 cqe->un.port.link_status[hba->sli.sli4.link_number]; 5466 5467 switch (status) { 5468 case 0 : 5469 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5470 "SLI Port Async Event: link%d misconfig " 5471 "functional", hba->sli.sli4.link_number); 5472 break; 5473 5474 case 1 : 5475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5476 "SLI Port Async Event: Physical media not " 5477 "detected"); 5478 cmn_err(CE_WARN, 5479 "^%s%d: Optics faulted/incorrectly " 5480 "installed/not installed - Reseat optics, " 5481 "if issue not resolved, replace.", 5482 DRIVER_NAME, hba->ddiinst); 5483 break; 5484 5485 case 2 : 5486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5487 "SLI Port Async Event: Wrong physical " 5488 "media detected"); 5489 cmn_err(CE_WARN, 5490 "^%s%d: Optics of two types installed - " 5491 "Remove one optic or install matching" 5492 "pair of optics.", 5493 DRIVER_NAME, hba->ddiinst); 5494 break; 5495 5496 case 3 : 5497 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5498 "SLI Port Async Event: Unsupported " 5499 "physical media detected"); 5500 cmn_err(CE_WARN, 5501 "^%s%d: Incompatible optics - Replace " 5502 "with compatible optics for card to " 5503 "function.", 5504 DRIVER_NAME, hba->ddiinst); 5505 break; 5506 5507 default : 5508 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 5509 "SLI Port Async Event: Physical media " 5510 "error, status=%x", status); 5511 cmn_err(CE_WARN, 5512 "^%s%d: Misconfigured port: status=0x%x - " 5513 "Check optics on card.", 5514 DRIVER_NAME, hba->ddiinst, status); 5515 break; 5516 } 5517 break; 5518 } 5519 5520 break; 5521 case ASYNC_EVENT_CODE_VF: 5522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5523 "VF Async Event: type=%d", 5524 cqe->event_type); 5525 break; 5526 case ASYNC_EVENT_CODE_MR: 5527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5528 "MR Async Event: type=%d", 5529 cqe->event_type); 5530 break; 5531 default: 5532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5533 "Unknown Async Event: code=%d type=%d.", 5534 cqe->event_code, cqe->event_type); 5535 break; 5536 } 5537 5538 } /* emlxs_sli4_process_async_event() */ 5539 5540 5541 /*ARGSUSED*/ 5542 static void 5543 emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) 5544 { 5545 emlxs_port_t *port = &PPORT; 5546 MAILBOX4 *mb; 5547 MATCHMAP *mbox_bp; 5548 MATCHMAP *mbox_nonembed; 5549 MAILBOXQ *mbq = NULL; 5550 uint32_t size; 5551 uint32_t *iptr; 5552 int rc; 5553 off_t offset; 5554 5555 if (cqe->consumed && !cqe->completed) { 5556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5557 "CQ ENTRY: Mbox event. Entry consumed but not completed"); 5558 return; 5559 } 5560 5561 mutex_enter(&EMLXS_PORT_LOCK); 5562 switch (hba->mbox_queue_flag) { 5563 case 0: 5564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 5565 "CQ ENTRY: Mbox event. No mailbox active."); 5566 5567 mutex_exit(&EMLXS_PORT_LOCK); 5568 return; 5569 5570 case MBX_POLL: 5571 5572 /* Mark mailbox complete, this should wake up any polling */ 5573 /* threads. This can happen if interrupts are enabled while */ 5574 /* a polled mailbox command is outstanding. If we don't set */ 5575 /* MBQ_COMPLETED here, the polling thread may wait until */ 5576 /* timeout error occurs */ 5577 5578 mutex_enter(&EMLXS_MBOX_LOCK); 5579 mbq = (MAILBOXQ *)hba->mbox_mbq; 5580 if (mbq) { 5581 port = (emlxs_port_t *)mbq->port; 5582 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5583 "CQ ENTRY: Mbox event. Completing Polled command."); 5584 mbq->flag |= MBQ_COMPLETED; 5585 } 5586 mutex_exit(&EMLXS_MBOX_LOCK); 5587 5588 mutex_exit(&EMLXS_PORT_LOCK); 5589 return; 5590 5591 case MBX_SLEEP: 5592 case MBX_NOWAIT: 5593 /* Check mbox_timer, it acts as a service flag too */ 5594 /* The first to service the mbox queue will clear the timer */ 5595 if (hba->mbox_timer) { 5596 hba->mbox_timer = 0; 5597 5598 mutex_enter(&EMLXS_MBOX_LOCK); 5599 mbq = (MAILBOXQ *)hba->mbox_mbq; 5600 mutex_exit(&EMLXS_MBOX_LOCK); 5601 } 5602 5603 if (!mbq) { 5604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5605 "Mailbox event. No service required."); 5606 mutex_exit(&EMLXS_PORT_LOCK); 5607 return; 5608 } 5609 5610 mb = (MAILBOX4 *)mbq; 5611 mutex_exit(&EMLXS_PORT_LOCK); 5612 break; 5613 5614 default: 5615 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, 5616 "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).", 5617 hba->mbox_queue_flag); 5618 5619 mutex_exit(&EMLXS_PORT_LOCK); 5620 return; 5621 } 5622 5623 /* Set port context */ 5624 port = (emlxs_port_t *)mbq->port; 5625 5626 offset = (off_t)((uint64_t)((unsigned long) 5627 hba->sli.sli4.mq.addr.virt) - 5628 (uint64_t)((unsigned long) 5629 hba->sli.sli4.slim2.virt)); 5630 5631 /* Now that we are the owner, DMA Sync entire MQ if needed */ 5632 EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset, 5633 4096, DDI_DMA_SYNC_FORDEV); 5634 5635 BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb, 5636 MAILBOX_CMD_SLI4_BSIZE); 5637 5638 if (mb->mbxCommand != MBX_HEARTBEAT) { 5639 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5640 "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x", 5641 mb->mbxStatus, mb->mbxCommand); 5642 5643 emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe, 5644 12, 0); 5645 } 5646 5647 if (mb->mbxCommand == MBX_SLI_CONFIG) { 5648 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5649 "Mbox sge_cnt: %d length: %d embed: %d", 5650 mb->un.varSLIConfig.be.sge_cnt, 5651 mb->un.varSLIConfig.be.payload_length, 5652 mb->un.varSLIConfig.be.embedded); 5653 } 5654 5655 /* Now sync the memory buffer if one was used */ 5656 if (mbq->bp) { 5657 mbox_bp = (MATCHMAP *)mbq->bp; 5658 EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size, 5659 DDI_DMA_SYNC_FORKERNEL); 5660 #ifdef FMA_SUPPORT 5661 if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle) 5662 != DDI_FM_OK) { 5663 EMLXS_MSGF(EMLXS_CONTEXT, 5664 &emlxs_invalid_dma_handle_msg, 5665 "sli4_process_mbox_event: hdl=%p", 5666 mbox_bp->dma_handle); 5667 5668 mb->mbxStatus = MBXERR_DMA_ERROR; 5669 } 5670 #endif 5671 } 5672 5673 /* Now sync the memory buffer if one was used */ 5674 if (mbq->nonembed) { 5675 mbox_nonembed = (MATCHMAP *)mbq->nonembed; 5676 size = mbox_nonembed->size; 5677 EMLXS_MPDATA_SYNC(mbox_nonembed->dma_handle, 0, size, 5678 DDI_DMA_SYNC_FORKERNEL); 5679 iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt); 5680 BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size); 5681 5682 #ifdef FMA_SUPPORT 5683 if (emlxs_fm_check_dma_handle(hba, 5684 mbox_nonembed->dma_handle) != DDI_FM_OK) { 5685 EMLXS_MSGF(EMLXS_CONTEXT, 5686 &emlxs_invalid_dma_handle_msg, 5687 "sli4_process_mbox_event: hdl=%p", 5688 mbox_nonembed->dma_handle); 5689 5690 mb->mbxStatus = MBXERR_DMA_ERROR; 5691 } 5692 #endif 5693 emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0); 5694 } 5695 5696 /* Mailbox has been completely received at this point */ 5697 5698 if (mb->mbxCommand == MBX_HEARTBEAT) { 5699 hba->heartbeat_active = 0; 5700 goto done; 5701 } 5702 5703 if (hba->mbox_queue_flag == MBX_SLEEP) { 5704 if (mb->mbxCommand != MBX_DOWN_LOAD 5705 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 5706 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5707 "Received. %s: status=%x Sleep.", 5708 emlxs_mb_cmd_xlate(mb->mbxCommand), 5709 mb->mbxStatus); 5710 } 5711 } else { 5712 if (mb->mbxCommand != MBX_DOWN_LOAD 5713 /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { 5714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5715 "Completed. %s: status=%x", 5716 emlxs_mb_cmd_xlate(mb->mbxCommand), 5717 mb->mbxStatus); 5718 } 5719 } 5720 5721 /* Filter out passthru mailbox */ 5722 if (mbq->flag & MBQ_PASSTHRU) { 5723 goto done; 5724 } 5725 5726 if (mb->mbxStatus) { 5727 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5728 "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 5729 (uint32_t)mb->mbxStatus); 5730 } 5731 5732 if (mbq->mbox_cmpl) { 5733 rc = (mbq->mbox_cmpl)(hba, mbq); 5734 5735 /* If mbox was retried, return immediately */ 5736 if (rc) { 5737 return; 5738 } 5739 } 5740 5741 done: 5742 5743 /* Clean up the mailbox area */ 5744 emlxs_mb_fini(hba, (MAILBOX *)mb, mb->mbxStatus); 5745 5746 /* Attempt to send pending mailboxes */ 5747 mbq = (MAILBOXQ *)emlxs_mb_get(hba); 5748 if (mbq) { 5749 /* Attempt to send pending mailboxes */ 5750 rc = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 5751 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 5752 emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 5753 } 5754 } 5755 return; 5756 5757 } /* emlxs_sli4_process_mbox_event() */ 5758 5759 5760 /*ARGSUSED*/ 5761 static void 5762 emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp) 5763 { 5764 #ifdef DEBUG_FASTPATH 5765 emlxs_port_t *port = &PPORT; 5766 #endif /* DEBUG_FASTPATH */ 5767 IOCBQ *iocbq; 5768 IOCB *iocb; 5769 uint32_t *iptr; 5770 fc_packet_t *pkt; 5771 emlxs_wqe_t *wqe; 5772 5773 iocbq = &sbp->iocbq; 5774 wqe = &iocbq->wqe; 5775 iocb = &iocbq->iocb; 5776 5777 #ifdef DEBUG_FASTPATH 5778 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5779 "CQE to IOCB: cmd:%x iotag:%x xri:%d", wqe->Command, 5780 wqe->RequestTag, wqe->XRITag); 5781 #endif /* DEBUG_FASTPATH */ 5782 5783 iocb->ULPSTATUS = cqe->Status; 5784 iocb->un.ulpWord[4] = cqe->Parameter; 5785 iocb->ULPIOTAG = cqe->RequestTag; 5786 iocb->ULPCONTEXT = wqe->XRITag; 5787 5788 switch (wqe->Command) { 5789 5790 case CMD_FCP_ICMND64_CR: 5791 iocb->ULPCOMMAND = CMD_FCP_ICMND64_CX; 5792 break; 5793 5794 case CMD_FCP_IREAD64_CR: 5795 iocb->ULPCOMMAND = CMD_FCP_IREAD64_CX; 5796 iocb->ULPPU = PARM_XFER_CHECK; 5797 if (iocb->ULPSTATUS == IOSTAT_FCP_RSP_ERROR) { 5798 iocb->un.fcpi64.fcpi_parm = 5799 wqe->un.FcpCmd.TotalTransferCount - 5800 cqe->CmdSpecific; 5801 } 5802 break; 5803 5804 case CMD_FCP_IWRITE64_CR: 5805 iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CX; 5806 if (iocb->ULPSTATUS == IOSTAT_FCP_RSP_ERROR) { 5807 if (wqe->un.FcpCmd.TotalTransferCount > 5808 cqe->CmdSpecific) { 5809 iocb->un.fcpi64.fcpi_parm = 5810 wqe->un.FcpCmd.TotalTransferCount - 5811 cqe->CmdSpecific; 5812 } else { 5813 iocb->un.fcpi64.fcpi_parm = 0; 5814 } 5815 } 5816 break; 5817 5818 case CMD_ELS_REQUEST64_CR: 5819 iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CX; 5820 iocb->un.elsreq64.bdl.bdeSize = cqe->CmdSpecific; 5821 if (iocb->ULPSTATUS == 0) { 5822 iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific; 5823 } 5824 if (iocb->ULPSTATUS == IOSTAT_LS_RJT) { 5825 /* For LS_RJT, the driver populates the rsp buffer */ 5826 pkt = PRIV2PKT(sbp); 5827 iptr = (uint32_t *)pkt->pkt_resp; 5828 *iptr++ = ELS_CMD_LS_RJT; 5829 *iptr = cqe->Parameter; 5830 } 5831 break; 5832 5833 case CMD_GEN_REQUEST64_CR: 5834 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX; 5835 iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific; 5836 break; 5837 5838 case CMD_XMIT_SEQUENCE64_CR: 5839 iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 5840 break; 5841 5842 case CMD_ABORT_XRI_CX: 5843 iocb->ULPCONTEXT = wqe->AbortTag; 5844 break; 5845 5846 case CMD_FCP_TRECEIVE64_CX: 5847 /* free memory for XRDY */ 5848 if (iocbq->bp) { 5849 emlxs_mem_buf_free(hba, iocbq->bp); 5850 iocbq->bp = 0; 5851 } 5852 5853 /*FALLTHROUGH*/ 5854 5855 case CMD_FCP_TSEND64_CX: 5856 case CMD_FCP_TRSP64_CX: 5857 default: 5858 iocb->ULPCOMMAND = wqe->Command; 5859 5860 } 5861 } /* emlxs_CQE_to_IOCB() */ 5862 5863 5864 /*ARGSUSED*/ 5865 static void 5866 emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba) 5867 { 5868 emlxs_port_t *port = &PPORT; 5869 CHANNEL *cp; 5870 emlxs_buf_t *sbp; 5871 IOCBQ *iocbq; 5872 uint16_t i; 5873 uint32_t trigger = 0; 5874 CQE_CmplWQ_t cqe; 5875 5876 mutex_enter(&EMLXS_FCTAB_LOCK); 5877 for (i = 0; i < hba->max_iotag; i++) { 5878 sbp = hba->fc_table[i]; 5879 if (sbp == NULL || sbp == STALE_PACKET) { 5880 continue; 5881 } 5882 hba->fc_table[i] = STALE_PACKET; 5883 hba->io_count--; 5884 sbp->iotag = 0; 5885 mutex_exit(&EMLXS_FCTAB_LOCK); 5886 5887 cp = sbp->channel; 5888 bzero(&cqe, sizeof (CQE_CmplWQ_t)); 5889 cqe.RequestTag = i; 5890 cqe.Status = IOSTAT_LOCAL_REJECT; 5891 cqe.Parameter = IOERR_SEQUENCE_TIMEOUT; 5892 5893 cp->hbaCmplCmd_sbp++; 5894 5895 #ifdef SFCT_SUPPORT 5896 #ifdef FCT_IO_TRACE 5897 if (sbp->fct_cmd) { 5898 emlxs_fct_io_trace(port, sbp->fct_cmd, 5899 EMLXS_FCT_IOCB_COMPLETE); 5900 } 5901 #endif /* FCT_IO_TRACE */ 5902 #endif /* SFCT_SUPPORT */ 5903 5904 if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 5905 atomic_dec_32(&hba->io_active); 5906 #ifdef NODE_THROTTLE_SUPPORT 5907 if (sbp->node) { 5908 atomic_dec_32(&sbp->node->io_active); 5909 } 5910 #endif /* NODE_THROTTLE_SUPPORT */ 5911 } 5912 5913 /* Copy entry to sbp's iocbq */ 5914 iocbq = &sbp->iocbq; 5915 emlxs_CQE_to_IOCB(hba, &cqe, sbp); 5916 5917 iocbq->next = NULL; 5918 5919 /* Exchange is no longer busy on-chip, free it */ 5920 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1); 5921 5922 if (!(sbp->pkt_flags & 5923 (PACKET_POLLED | PACKET_ALLOCATED))) { 5924 /* Add the IOCB to the channel list */ 5925 mutex_enter(&cp->rsp_lock); 5926 if (cp->rsp_head == NULL) { 5927 cp->rsp_head = iocbq; 5928 cp->rsp_tail = iocbq; 5929 } else { 5930 cp->rsp_tail->next = iocbq; 5931 cp->rsp_tail = iocbq; 5932 } 5933 mutex_exit(&cp->rsp_lock); 5934 trigger = 1; 5935 } else { 5936 emlxs_proc_channel_event(hba, cp, iocbq); 5937 } 5938 mutex_enter(&EMLXS_FCTAB_LOCK); 5939 } 5940 mutex_exit(&EMLXS_FCTAB_LOCK); 5941 5942 if (trigger) { 5943 for (i = 0; i < hba->chan_count; i++) { 5944 cp = &hba->chan[i]; 5945 if (cp->rsp_head != NULL) { 5946 emlxs_thread_trigger2(&cp->intr_thread, 5947 emlxs_proc_channel, cp); 5948 } 5949 } 5950 } 5951 5952 } /* emlxs_sli4_hba_flush_chipq() */ 5953 5954 5955 /*ARGSUSED*/ 5956 static void 5957 emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba, 5958 CQ_DESC_t *cq, CQE_CmplWQ_t *cqe) 5959 { 5960 emlxs_port_t *port = &PPORT; 5961 CHANNEL *cp; 5962 uint16_t request_tag; 5963 5964 request_tag = cqe->RequestTag; 5965 5966 /* 1 to 1 mapping between CQ and channel */ 5967 cp = cq->channelp; 5968 5969 cp->hbaCmplCmd++; 5970 5971 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 5972 "CQ ENTRY: OOR Cmpl: iotag=%d", request_tag); 5973 5974 emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 4, 0); 5975 5976 } /* emlxs_sli4_process_oor_wqe_cmpl() */ 5977 5978 5979 /*ARGSUSED*/ 5980 static void 5981 emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe) 5982 { 5983 emlxs_port_t *port = &PPORT; 5984 CHANNEL *cp; 5985 emlxs_buf_t *sbp; 5986 IOCBQ *iocbq; 5987 uint16_t request_tag; 5988 #ifdef SFCT_SUPPORT 5989 #ifdef FCT_IO_TRACE 5990 fct_cmd_t *fct_cmd; 5991 emlxs_buf_t *cmd_sbp; 5992 #endif /* FCT_IO_TRACE */ 5993 #endif /* SFCT_SUPPORT */ 5994 5995 request_tag = cqe->RequestTag; 5996 5997 /* 1 to 1 mapping between CQ and channel */ 5998 cp = cq->channelp; 5999 6000 mutex_enter(&EMLXS_FCTAB_LOCK); 6001 sbp = hba->fc_table[request_tag]; 6002 6003 if (!sbp) { 6004 cp->hbaCmplCmd++; 6005 mutex_exit(&EMLXS_FCTAB_LOCK); 6006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6007 "CQ ENTRY: NULL sbp. iotag=%d. Dropping...", 6008 request_tag); 6009 return; 6010 } 6011 6012 if (sbp == STALE_PACKET) { 6013 cp->hbaCmplCmd_sbp++; 6014 mutex_exit(&EMLXS_FCTAB_LOCK); 6015 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6016 "CQ ENTRY: Stale sbp. iotag=%d. Dropping...", request_tag); 6017 return; 6018 } 6019 6020 if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 6021 atomic_add_32(&hba->io_active, -1); 6022 #ifdef NODE_THROTTLE_SUPPORT 6023 if (sbp->node) { 6024 atomic_add_32(&sbp->node->io_active, -1); 6025 } 6026 #endif /* NODE_THROTTLE_SUPPORT */ 6027 } 6028 6029 if (!(sbp->xrip)) { 6030 cp->hbaCmplCmd++; 6031 mutex_exit(&EMLXS_FCTAB_LOCK); 6032 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6033 "CQ ENTRY: NULL sbp xrip %p. iotag=%d. Dropping...", 6034 sbp, request_tag); 6035 return; 6036 } 6037 6038 #ifdef DEBUG_FASTPATH 6039 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6040 "CQ ENTRY: process wqe compl"); 6041 #endif /* DEBUG_FASTPATH */ 6042 cp->hbaCmplCmd_sbp++; 6043 6044 /* Copy entry to sbp's iocbq */ 6045 iocbq = &sbp->iocbq; 6046 emlxs_CQE_to_IOCB(hba, cqe, sbp); 6047 6048 iocbq->next = NULL; 6049 6050 if (cqe->XB) { 6051 /* Mark exchange as ABORT in progress */ 6052 sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO; 6053 sbp->xrip->flag |= EMLXS_XRI_BUSY; 6054 6055 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6056 "CQ ENTRY: XRI BUSY: iotag=%d xri=%d", request_tag, 6057 sbp->xrip->XRI); 6058 6059 emlxs_sli4_free_xri(port, sbp, 0, 0); 6060 } else { 6061 /* Exchange is no longer busy on-chip, free it */ 6062 emlxs_sli4_free_xri(port, sbp, sbp->xrip, 0); 6063 } 6064 6065 mutex_exit(&EMLXS_FCTAB_LOCK); 6066 6067 #ifdef SFCT_SUPPORT 6068 #ifdef FCT_IO_TRACE 6069 fct_cmd = sbp->fct_cmd; 6070 if (fct_cmd) { 6071 cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; 6072 mutex_enter(&cmd_sbp->fct_mtx); 6073 EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE); 6074 mutex_exit(&cmd_sbp->fct_mtx); 6075 } 6076 #endif /* FCT_IO_TRACE */ 6077 #endif /* SFCT_SUPPORT */ 6078 6079 /* 6080 * If this is NOT a polled command completion 6081 * or a driver allocated pkt, then defer pkt 6082 * completion. 6083 */ 6084 if (!(sbp->pkt_flags & 6085 (PACKET_POLLED | PACKET_ALLOCATED))) { 6086 /* Add the IOCB to the channel list */ 6087 mutex_enter(&cp->rsp_lock); 6088 if (cp->rsp_head == NULL) { 6089 cp->rsp_head = iocbq; 6090 cp->rsp_tail = iocbq; 6091 } else { 6092 cp->rsp_tail->next = iocbq; 6093 cp->rsp_tail = iocbq; 6094 } 6095 mutex_exit(&cp->rsp_lock); 6096 6097 /* Delay triggering thread till end of ISR */ 6098 cp->chan_flag |= EMLXS_NEEDS_TRIGGER; 6099 } else { 6100 emlxs_proc_channel_event(hba, cp, iocbq); 6101 } 6102 6103 } /* emlxs_sli4_process_wqe_cmpl() */ 6104 6105 6106 /*ARGSUSED*/ 6107 static void 6108 emlxs_sli4_process_release_wqe(emlxs_hba_t *hba, CQ_DESC_t *cq, 6109 CQE_RelWQ_t *cqe) 6110 { 6111 emlxs_port_t *port = &PPORT; 6112 WQ_DESC_t *wq; 6113 CHANNEL *cp; 6114 uint32_t i; 6115 uint16_t wqi; 6116 6117 wqi = emlxs_sli4_wqid_to_index(hba, (uint16_t)cqe->WQid); 6118 6119 /* Verify WQ index */ 6120 if (wqi == 0xffff) { 6121 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6122 "CQ ENTRY: Invalid WQid:%d. Dropping...", 6123 cqe->WQid); 6124 return; 6125 } 6126 6127 wq = &hba->sli.sli4.wq[wqi]; 6128 6129 #ifdef DEBUG_FASTPATH 6130 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6131 "CQ ENTRY: process release wqe: old %d new %d", wq->port_index, 6132 cqe->WQindex); 6133 #endif /* DEBUG_FASTPATH */ 6134 6135 wq->port_index = cqe->WQindex; 6136 6137 /* Cmd ring may be available. Try sending more iocbs */ 6138 for (i = 0; i < hba->chan_count; i++) { 6139 cp = &hba->chan[i]; 6140 if (wq == (WQ_DESC_t *)cp->iopath) { 6141 emlxs_sli4_issue_iocb_cmd(hba, cp, 0); 6142 } 6143 } 6144 6145 } /* emlxs_sli4_process_release_wqe() */ 6146 6147 6148 /*ARGSUSED*/ 6149 emlxs_iocbq_t * 6150 emlxs_sli4_rxq_get(emlxs_hba_t *hba, fc_frame_hdr_t *fchdr) 6151 { 6152 emlxs_queue_t *q; 6153 emlxs_iocbq_t *iocbq; 6154 emlxs_iocbq_t *prev; 6155 fc_frame_hdr_t *fchdr2; 6156 RXQ_DESC_t *rxq; 6157 6158 switch (fchdr->type) { 6159 case 1: /* ELS */ 6160 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS]; 6161 break; 6162 case 0x20: /* CT */ 6163 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT]; 6164 break; 6165 default: 6166 return (NULL); 6167 } 6168 6169 mutex_enter(&rxq->lock); 6170 6171 q = &rxq->active; 6172 iocbq = (emlxs_iocbq_t *)q->q_first; 6173 prev = NULL; 6174 6175 while (iocbq) { 6176 6177 fchdr2 = (fc_frame_hdr_t *)iocbq->iocb.un.ulpWord; 6178 6179 if ((fchdr2->s_id == fchdr->s_id) && 6180 (fchdr2->ox_id == fchdr->ox_id) && 6181 (fchdr2->seq_id == fchdr->seq_id)) { 6182 /* Remove iocbq */ 6183 if (prev) { 6184 prev->next = iocbq->next; 6185 } 6186 if (q->q_first == (uint8_t *)iocbq) { 6187 q->q_first = (uint8_t *)iocbq->next; 6188 } 6189 if (q->q_last == (uint8_t *)iocbq) { 6190 q->q_last = (uint8_t *)prev; 6191 } 6192 q->q_cnt--; 6193 6194 break; 6195 } 6196 6197 prev = iocbq; 6198 iocbq = iocbq->next; 6199 } 6200 6201 mutex_exit(&rxq->lock); 6202 6203 return (iocbq); 6204 6205 } /* emlxs_sli4_rxq_get() */ 6206 6207 6208 /*ARGSUSED*/ 6209 void 6210 emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq) 6211 { 6212 emlxs_queue_t *q; 6213 fc_frame_hdr_t *fchdr; 6214 RXQ_DESC_t *rxq; 6215 6216 fchdr = (fc_frame_hdr_t *)iocbq->iocb.RXFCHDR; 6217 6218 switch (fchdr->type) { 6219 case 1: /* ELS */ 6220 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_ELS]; 6221 break; 6222 case 0x20: /* CT */ 6223 rxq = &hba->sli.sli4.rxq[EMLXS_RXQ_CT]; 6224 break; 6225 default: 6226 return; 6227 } 6228 6229 mutex_enter(&rxq->lock); 6230 6231 q = &rxq->active; 6232 6233 if (q->q_last) { 6234 ((emlxs_iocbq_t *)q->q_last)->next = iocbq; 6235 q->q_cnt++; 6236 } else { 6237 q->q_first = (uint8_t *)iocbq; 6238 q->q_cnt = 1; 6239 } 6240 6241 q->q_last = (uint8_t *)iocbq; 6242 iocbq->next = NULL; 6243 6244 mutex_exit(&rxq->lock); 6245 6246 return; 6247 6248 } /* emlxs_sli4_rxq_put() */ 6249 6250 6251 static void 6252 emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid) 6253 { 6254 emlxs_hba_t *hba = HBA; 6255 6256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6257 "RQ POST: rqid=%d count=1", rqid); 6258 6259 /* Ring the RQ doorbell once to repost the RQ buffer */ 6260 6261 emlxs_sli4_write_rqdb(hba, rqid, 1); 6262 6263 } /* emlxs_sli4_rq_post() */ 6264 6265 6266 /*ARGSUSED*/ 6267 static void 6268 emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, 6269 CQE_UnsolRcv_t *cqe) 6270 { 6271 emlxs_port_t *port = &PPORT; 6272 emlxs_port_t *vport; 6273 RQ_DESC_t *hdr_rq; 6274 RQ_DESC_t *data_rq; 6275 MBUF_INFO *hdr_mp; 6276 MBUF_INFO *data_mp; 6277 MATCHMAP *seq_mp; 6278 uint32_t *data; 6279 fc_frame_hdr_t fchdr; 6280 uint16_t hdr_rqi; 6281 uint32_t host_index; 6282 emlxs_iocbq_t *iocbq = NULL; 6283 emlxs_iocb_t *iocb; 6284 emlxs_node_t *node = NULL; 6285 uint32_t i; 6286 uint32_t seq_len; 6287 uint32_t seq_cnt; 6288 uint32_t buf_type; 6289 char label[32]; 6290 emlxs_wqe_t *wqe; 6291 CHANNEL *cp; 6292 XRIobj_t *xrip; 6293 RPIobj_t *rpip = NULL; 6294 uint32_t cmd; 6295 uint32_t posted = 0; 6296 uint32_t abort = 1; 6297 off_t offset; 6298 uint32_t status; 6299 uint32_t data_size; 6300 uint16_t rqid; 6301 uint32_t hdr_size; 6302 fc_packet_t *pkt; 6303 emlxs_buf_t *sbp; 6304 6305 if (cqe->Code == CQE_TYPE_UNSOL_RCV_V1) { 6306 CQE_UnsolRcvV1_t *cqeV1 = (CQE_UnsolRcvV1_t *)cqe; 6307 6308 status = cqeV1->Status; 6309 data_size = cqeV1->data_size; 6310 rqid = cqeV1->RQid; 6311 hdr_size = cqeV1->hdr_size; 6312 } else { 6313 status = cqe->Status; 6314 data_size = cqe->data_size; 6315 rqid = cqe->RQid; 6316 hdr_size = cqe->hdr_size; 6317 } 6318 6319 /* Validate the CQE */ 6320 6321 /* Check status */ 6322 switch (status) { 6323 case RQ_STATUS_SUCCESS: /* 0x10 */ 6324 break; 6325 6326 case RQ_STATUS_BUFLEN_EXCEEDED: /* 0x11 */ 6327 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6328 "CQ ENTRY: Unsol Rcv: Payload truncated."); 6329 break; 6330 6331 case RQ_STATUS_NEED_BUFFER: /* 0x12 */ 6332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6333 "CQ ENTRY: Unsol Rcv: Payload buffer needed."); 6334 return; 6335 6336 case RQ_STATUS_FRAME_DISCARDED: /* 0x13 */ 6337 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6338 "CQ ENTRY: Unsol Rcv: Payload buffer discarded."); 6339 return; 6340 6341 default: 6342 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6343 "CQ ENTRY: Unsol Rcv: Unknown status=%x.", 6344 status); 6345 break; 6346 } 6347 6348 /* Make sure there is a frame header */ 6349 if (hdr_size < sizeof (fc_frame_hdr_t)) { 6350 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6351 "CQ ENTRY: Unsol Rcv: FC header too small. Dropping..."); 6352 return; 6353 } 6354 6355 hdr_rqi = emlxs_sli4_rqid_to_index(hba, rqid); 6356 6357 /* Verify RQ index */ 6358 if (hdr_rqi == 0xffff) { 6359 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6360 "CQ ENTRY: Unsol Rcv: Invalid RQID:%d. Dropping...", 6361 rqid); 6362 return; 6363 } 6364 6365 hdr_rq = &hba->sli.sli4.rq[hdr_rqi]; 6366 data_rq = &hba->sli.sli4.rq[hdr_rqi + 1]; 6367 6368 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6369 "CQ ENTRY: Unsol Rcv:%x rqid=%d,%d index=%d status=%x " 6370 "hdr_size=%d data_size=%d", 6371 cqe->Code, rqid, hdr_rqi, hdr_rq->host_index, status, hdr_size, 6372 data_size); 6373 6374 hdr_rq->num_proc++; 6375 6376 /* Update host index */ 6377 mutex_enter(&hba->sli.sli4.rq[hdr_rqi].lock); 6378 host_index = hdr_rq->host_index; 6379 hdr_rq->host_index++; 6380 6381 if (hdr_rq->host_index >= hdr_rq->max_index) { 6382 hdr_rq->host_index = 0; 6383 } 6384 data_rq->host_index = hdr_rq->host_index; 6385 mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock); 6386 6387 /* Get the next header rqb */ 6388 hdr_mp = &hdr_rq->rqb[host_index]; 6389 6390 offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) - 6391 (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt)); 6392 6393 EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset, 6394 sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL); 6395 6396 LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr, 6397 sizeof (fc_frame_hdr_t)); 6398 6399 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6400 "RQ HDR[%d]: rctl:%x type:%x " 6401 "sid:%x did:%x oxid:%x rxid:%x", 6402 host_index, fchdr.r_ctl, fchdr.type, 6403 fchdr.s_id, fchdr.d_id, fchdr.ox_id, fchdr.rx_id); 6404 6405 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6406 "RQ HDR[%d]: fctl:%x seq_id:%x seq_cnt:%x df_ctl:%x ro:%x", 6407 host_index, fchdr.f_ctl, fchdr.seq_id, fchdr.seq_cnt, 6408 fchdr.df_ctl, fchdr.ro); 6409 6410 /* Verify fc header type */ 6411 switch (fchdr.type) { 6412 case 0: /* BLS */ 6413 if (fchdr.r_ctl != 0x81) { 6414 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6415 "RQ ENTRY: Unexpected FC rctl (0x%x) " 6416 "received. Dropping...", 6417 fchdr.r_ctl); 6418 6419 goto done; 6420 } 6421 6422 /* Make sure there is no payload */ 6423 if (data_size != 0) { 6424 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6425 "RQ ENTRY: ABTS payload provided. Dropping..."); 6426 6427 goto done; 6428 } 6429 6430 buf_type = 0xFFFFFFFF; 6431 (void) strlcpy(label, "ABTS", sizeof (label)); 6432 cp = &hba->chan[hba->channel_els]; 6433 break; 6434 6435 case 0x01: /* ELS */ 6436 /* Make sure there is a payload */ 6437 if (data_size == 0) { 6438 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6439 "RQ ENTRY: Unsol Rcv: No ELS payload provided. " 6440 "Dropping..."); 6441 6442 goto done; 6443 } 6444 6445 buf_type = MEM_ELSBUF; 6446 (void) strlcpy(label, "Unsol ELS", sizeof (label)); 6447 cp = &hba->chan[hba->channel_els]; 6448 break; 6449 6450 case 0x20: /* CT */ 6451 /* Make sure there is a payload */ 6452 if (data_size == 0) { 6453 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6454 "RQ ENTRY: Unsol Rcv: No CT payload provided. " 6455 "Dropping..."); 6456 6457 goto done; 6458 } 6459 6460 buf_type = MEM_CTBUF; 6461 (void) strlcpy(label, "Unsol CT", sizeof (label)); 6462 cp = &hba->chan[hba->channel_ct]; 6463 break; 6464 6465 case 0x08: /* FCT */ 6466 /* Make sure there is a payload */ 6467 if (data_size == 0) { 6468 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6469 "RQ ENTRY: Unsol Rcv: No FCP payload provided. " 6470 "Dropping..."); 6471 6472 goto done; 6473 } 6474 6475 buf_type = MEM_FCTBUF; 6476 (void) strlcpy(label, "Unsol FCT", sizeof (label)); 6477 cp = &hba->chan[hba->CHANNEL_FCT]; 6478 break; 6479 6480 default: 6481 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6482 "RQ ENTRY: Unexpected FC type (0x%x) received. Dropping...", 6483 fchdr.type); 6484 6485 goto done; 6486 } 6487 /* Fc Header is valid */ 6488 6489 /* Check if this is an active sequence */ 6490 iocbq = emlxs_sli4_rxq_get(hba, &fchdr); 6491 6492 if (!iocbq) { 6493 if (fchdr.type != 0) { 6494 if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) { 6495 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6496 "RQ ENTRY: %s: First of sequence not" 6497 " set. Dropping...", 6498 label); 6499 6500 goto done; 6501 } 6502 } 6503 6504 if ((fchdr.type != 0) && (fchdr.seq_cnt != 0)) { 6505 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6506 "RQ ENTRY: %s: Sequence count not zero (%d). " 6507 "Dropping...", 6508 label, fchdr.seq_cnt); 6509 6510 goto done; 6511 } 6512 6513 /* Find vport */ 6514 for (i = 0; i < MAX_VPORTS; i++) { 6515 vport = &VPORT(i); 6516 6517 if (vport->did == fchdr.d_id) { 6518 port = vport; 6519 break; 6520 } 6521 } 6522 6523 if (i == MAX_VPORTS) { 6524 /* Allow unsol FLOGI & PLOGI for P2P */ 6525 if ((fchdr.type != 1 /* ELS*/) || 6526 ((fchdr.d_id != FABRIC_DID) && 6527 !(hba->flag & FC_PT_TO_PT))) { 6528 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6529 "RQ ENTRY: %s: Invalid did=%x. Dropping...", 6530 label, fchdr.d_id); 6531 6532 goto done; 6533 } 6534 } 6535 6536 /* Allocate an IOCBQ */ 6537 iocbq = (emlxs_iocbq_t *)emlxs_mem_get(hba, MEM_IOCB); 6538 6539 if (!iocbq) { 6540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6541 "RQ ENTRY: %s: Out of IOCB " 6542 "resources. Dropping...", 6543 label); 6544 6545 goto done; 6546 } 6547 6548 seq_mp = NULL; 6549 if (fchdr.type != 0) { 6550 /* Allocate a buffer */ 6551 seq_mp = (MATCHMAP *)emlxs_mem_get(hba, buf_type); 6552 6553 if (!seq_mp) { 6554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6555 "RQ ENTRY: %s: Out of buffer " 6556 "resources. Dropping...", 6557 label); 6558 6559 goto done; 6560 } 6561 6562 iocbq->bp = (uint8_t *)seq_mp; 6563 } 6564 6565 node = (void *)emlxs_node_find_did(port, fchdr.s_id, 1); 6566 if (node == NULL) { 6567 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6568 "RQ ENTRY: %s: Node not found. sid=%x", 6569 label, fchdr.s_id); 6570 } 6571 6572 /* Initialize the iocbq */ 6573 iocbq->port = port; 6574 iocbq->channel = cp; 6575 iocbq->node = node; 6576 6577 iocb = &iocbq->iocb; 6578 iocb->RXSEQCNT = 0; 6579 iocb->RXSEQLEN = 0; 6580 6581 seq_len = 0; 6582 seq_cnt = 0; 6583 6584 } else { 6585 6586 iocb = &iocbq->iocb; 6587 port = iocbq->port; 6588 node = (emlxs_node_t *)iocbq->node; 6589 6590 seq_mp = (MATCHMAP *)iocbq->bp; 6591 seq_len = iocb->RXSEQLEN; 6592 seq_cnt = iocb->RXSEQCNT; 6593 6594 /* Check sequence order */ 6595 if (fchdr.seq_cnt != seq_cnt) { 6596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6597 "RQ ENTRY: %s: Out of order frame received " 6598 "(%d != %d). Dropping...", 6599 label, fchdr.seq_cnt, seq_cnt); 6600 6601 goto done; 6602 } 6603 } 6604 6605 /* We now have an iocbq */ 6606 6607 if (!port->vpip->vfip) { 6608 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6609 "RQ ENTRY: %s: No fabric connection. " 6610 "Dropping...", 6611 label); 6612 6613 goto done; 6614 } 6615 6616 /* Save the frame data to our seq buffer */ 6617 if (data_size && seq_mp) { 6618 /* Get the next data rqb */ 6619 data_mp = &data_rq->rqb[host_index]; 6620 6621 offset = (off_t)((uint64_t)((unsigned long) 6622 data_mp->virt) - 6623 (uint64_t)((unsigned long) 6624 hba->sli.sli4.slim2.virt)); 6625 6626 EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset, 6627 data_size, DDI_DMA_SYNC_FORKERNEL); 6628 6629 data = (uint32_t *)data_mp->virt; 6630 6631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6632 "RQ DAT[%d]: %08x %08x %08x %08x %08x %08x ...", 6633 host_index, data[0], data[1], data[2], data[3], 6634 data[4], data[5]); 6635 6636 /* Check sequence length */ 6637 if ((seq_len + data_size) > seq_mp->size) { 6638 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 6639 "RQ ENTRY: %s: Sequence buffer overflow. " 6640 "(%d > %d). Dropping...", 6641 label, (seq_len + data_size), seq_mp->size); 6642 6643 goto done; 6644 } 6645 6646 /* Copy data to local receive buffer */ 6647 bcopy((uint8_t *)data, ((uint8_t *)seq_mp->virt + 6648 seq_len), data_size); 6649 6650 seq_len += data_size; 6651 } 6652 6653 /* If this is not the last frame of sequence, queue it. */ 6654 if (!(fchdr.f_ctl & F_CTL_END_SEQ)) { 6655 /* Save sequence header */ 6656 if (seq_cnt == 0) { 6657 bcopy((uint8_t *)&fchdr, (uint8_t *)iocb->RXFCHDR, 6658 sizeof (fc_frame_hdr_t)); 6659 } 6660 6661 /* Update sequence info in iocb */ 6662 iocb->RXSEQCNT = seq_cnt + 1; 6663 iocb->RXSEQLEN = seq_len; 6664 6665 /* Queue iocbq for next frame */ 6666 emlxs_sli4_rxq_put(hba, iocbq); 6667 6668 /* Don't free resources */ 6669 iocbq = NULL; 6670 6671 /* No need to abort */ 6672 abort = 0; 6673 6674 goto done; 6675 } 6676 6677 emlxs_sli4_rq_post(port, hdr_rq->qid); 6678 posted = 1; 6679 6680 /* End of sequence found. Process request now. */ 6681 6682 if (seq_cnt > 0) { 6683 /* Retrieve first frame of sequence */ 6684 bcopy((uint8_t *)iocb->RXFCHDR, (uint8_t *)&fchdr, 6685 sizeof (fc_frame_hdr_t)); 6686 6687 bzero((uint8_t *)iocb, sizeof (emlxs_iocb_t)); 6688 } 6689 6690 /* Build rcv iocb and process it */ 6691 switch (fchdr.type) { 6692 case 0: /* BLS */ 6693 6694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6695 "RQ ENTRY: %s: oxid:%x rxid %x sid:%x. Sending BLS ACC...", 6696 label, fchdr.ox_id, fchdr.rx_id, fchdr.s_id); 6697 6698 /* Try to send abort response */ 6699 if (!(pkt = emlxs_pkt_alloc(port, 0, 0, 0, KM_NOSLEEP))) { 6700 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6701 "RQ ENTRY: %s: Unable to alloc pkt. Dropping...", 6702 label); 6703 goto done; 6704 } 6705 6706 /* Setup sbp / iocb for driver initiated cmd */ 6707 sbp = PKT2PRIV(pkt); 6708 6709 /* Free the temporary iocbq */ 6710 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 6711 6712 iocbq = (emlxs_iocbq_t *)&sbp->iocbq; 6713 iocbq->port = port; 6714 iocbq->channel = cp; 6715 iocbq->node = node; 6716 6717 sbp->pkt_flags &= ~PACKET_ULP_OWNED; 6718 6719 if (node) { 6720 sbp->node = node; 6721 sbp->did = node->nlp_DID; 6722 } 6723 6724 iocbq->flag |= (IOCB_PRIORITY | IOCB_SPECIAL); 6725 6726 /* BLS ACC Response */ 6727 wqe = &iocbq->wqe; 6728 bzero((void *)wqe, sizeof (emlxs_wqe_t)); 6729 6730 iocbq->iocb.ULPCOMMAND = CMD_XMIT_BLS_RSP64_CX; 6731 wqe->Command = CMD_XMIT_BLS_RSP64_CX; 6732 wqe->CmdType = WQE_TYPE_GEN; 6733 6734 wqe->un.BlsRsp.Payload0 = 0x80; 6735 wqe->un.BlsRsp.Payload1 = fchdr.seq_id; 6736 6737 wqe->un.BlsRsp.OXId = fchdr.ox_id; 6738 wqe->un.BlsRsp.RXId = fchdr.rx_id; 6739 6740 wqe->un.BlsRsp.SeqCntLow = 0; 6741 wqe->un.BlsRsp.SeqCntHigh = 0xFFFF; 6742 6743 wqe->un.BlsRsp.XO = ((fchdr.f_ctl & F_CTL_XCHG_CONTEXT)? 1:0); 6744 wqe->un.BlsRsp.AR = 0; 6745 6746 rpip = EMLXS_NODE_TO_RPI(port, node); 6747 6748 if (rpip) { 6749 wqe->ContextType = WQE_RPI_CONTEXT; 6750 wqe->ContextTag = rpip->RPI; 6751 } else { 6752 wqe->ContextType = WQE_VPI_CONTEXT; 6753 wqe->ContextTag = port->vpip->VPI; 6754 6755 rpip = emlxs_rpi_reserve_notify(port, fchdr.s_id, 0); 6756 6757 if (!rpip) { 6758 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6759 "RQ ENTRY: %s: Unable to alloc " 6760 "reserved RPI. Dropping...", 6761 label); 6762 6763 goto done; 6764 } 6765 6766 /* Store the reserved rpi */ 6767 wqe->CmdSpecific = rpip->RPI; 6768 6769 wqe->un.BlsRsp.RemoteId = fchdr.s_id; 6770 wqe->un.BlsRsp.LocalId = fchdr.d_id; 6771 } 6772 6773 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { 6774 wqe->CCPE = 1; 6775 wqe->CCP = fchdr.rsvd; 6776 } 6777 6778 /* Allocate an exchange for this command */ 6779 xrip = emlxs_sli4_alloc_xri(port, sbp, rpip, 6780 EMLXS_XRI_SOL_BLS_TYPE); 6781 6782 if (!xrip) { 6783 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6784 "RQ ENTRY: %s: Unable to alloc XRI. Dropping...", 6785 label); 6786 goto done; 6787 } 6788 6789 wqe->XRITag = xrip->XRI; 6790 wqe->Class = CLASS3; 6791 wqe->RequestTag = xrip->iotag; 6792 wqe->CQId = (uint16_t)0xffff; /* default CQ for response */ 6793 6794 sbp->ticks = hba->timer_tics + 30; 6795 6796 emlxs_sli4_issue_iocb_cmd(hba, iocbq->channel, iocbq); 6797 6798 /* The temporary iocbq has been freed already */ 6799 iocbq = NULL; 6800 6801 break; 6802 6803 case 1: /* ELS */ 6804 cmd = *((uint32_t *)seq_mp->virt); 6805 cmd &= ELS_CMD_MASK; 6806 6807 if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED)) { 6808 uint32_t dropit = 1; 6809 6810 /* Allow for P2P handshaking */ 6811 switch (cmd) { 6812 case ELS_CMD_FLOGI: 6813 dropit = 0; 6814 break; 6815 6816 case ELS_CMD_PLOGI: 6817 case ELS_CMD_PRLI: 6818 if (hba->flag & FC_PT_TO_PT) { 6819 dropit = 0; 6820 } 6821 break; 6822 } 6823 6824 if (dropit) { 6825 EMLXS_MSGF(EMLXS_CONTEXT, 6826 &emlxs_sli_detail_msg, 6827 "RQ ENTRY: %s: Port not yet enabled. " 6828 "Dropping...", 6829 label); 6830 goto done; 6831 } 6832 } 6833 6834 rpip = NULL; 6835 6836 if (cmd != ELS_CMD_LOGO) { 6837 rpip = EMLXS_NODE_TO_RPI(port, node); 6838 } 6839 6840 if (!rpip) { 6841 /* Use the fabric rpi */ 6842 rpip = port->vpip->fabric_rpip; 6843 } 6844 6845 xrip = emlxs_sli4_reserve_xri(port, rpip, 6846 EMLXS_XRI_UNSOL_ELS_TYPE, fchdr.ox_id); 6847 6848 if (!xrip) { 6849 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6850 "RQ ENTRY: %s: Out of exchange " 6851 "resources. Dropping...", 6852 label); 6853 6854 goto done; 6855 } 6856 6857 /* Build CMD_RCV_ELS64_CX */ 6858 iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0; 6859 iocb->un.rcvels64.elsReq.tus.f.bdeSize = seq_len; 6860 iocb->un.rcvels64.elsReq.addrLow = PADDR_LO(seq_mp->phys); 6861 iocb->un.rcvels64.elsReq.addrHigh = PADDR_HI(seq_mp->phys); 6862 iocb->ULPBDECOUNT = 1; 6863 6864 iocb->un.rcvels64.remoteID = fchdr.s_id; 6865 iocb->un.rcvels64.parmRo = fchdr.d_id; 6866 6867 iocb->ULPPU = 0x3; 6868 iocb->ULPCONTEXT = xrip->XRI; 6869 iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0); 6870 iocb->ULPCLASS = CLASS3; 6871 iocb->ULPCOMMAND = CMD_RCV_ELS64_CX; 6872 6873 iocb->unsli3.ext_rcv.seq_len = seq_len; 6874 iocb->unsli3.ext_rcv.vpi = port->vpip->VPI; 6875 iocb->unsli3.ext_rcv.oxid = fchdr.ox_id; 6876 6877 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { 6878 iocb->unsli3.ext_rcv.ccpe = 1; 6879 iocb->unsli3.ext_rcv.ccp = fchdr.rsvd; 6880 } 6881 6882 if (port->mode == MODE_INITIATOR) { 6883 (void) emlxs_els_handle_unsol_req(port, iocbq->channel, 6884 iocbq, seq_mp, seq_len); 6885 } 6886 #ifdef SFCT_SUPPORT 6887 else if (port->mode == MODE_TARGET) { 6888 (void) emlxs_fct_handle_unsol_els(port, iocbq->channel, 6889 iocbq, seq_mp, seq_len); 6890 } 6891 #endif /* SFCT_SUPPORT */ 6892 break; 6893 6894 #ifdef SFCT_SUPPORT 6895 case 8: /* FCT */ 6896 if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) { 6897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6898 "RQ ENTRY: %s: Port not yet enabled. " 6899 "Dropping...", 6900 label); 6901 6902 goto done; 6903 } 6904 6905 rpip = EMLXS_NODE_TO_RPI(port, node); 6906 6907 if (!rpip) { 6908 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6909 "RQ ENTRY: %s: Port not logged in. " 6910 "Dropping...", 6911 label); 6912 6913 goto done; 6914 } 6915 6916 xrip = emlxs_sli4_reserve_xri(port, rpip, 6917 EMLXS_XRI_UNSOL_FCP_TYPE, fchdr.ox_id); 6918 6919 if (!xrip) { 6920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6921 "RQ ENTRY: %s: Out of exchange " 6922 "resources. Dropping...", 6923 label); 6924 6925 goto done; 6926 } 6927 6928 /* Build CMD_RCV_SEQUENCE64_CX */ 6929 iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0; 6930 iocb->un.rcvseq64.rcvBde.tus.f.bdeSize = seq_len; 6931 iocb->un.rcvseq64.rcvBde.addrLow = PADDR_LO(seq_mp->phys); 6932 iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys); 6933 iocb->ULPBDECOUNT = 1; 6934 6935 iocb->ULPPU = 0x3; 6936 iocb->ULPCONTEXT = xrip->XRI; 6937 iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0); 6938 iocb->ULPCLASS = CLASS3; 6939 iocb->ULPCOMMAND = CMD_RCV_ELS64_CX; 6940 6941 iocb->unsli3.ext_rcv.seq_len = seq_len; 6942 iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI; 6943 iocb->unsli3.ext_rcv.oxid = fchdr.ox_id; 6944 6945 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { 6946 iocb->unsli3.ext_rcv.ccpe = 1; 6947 iocb->unsli3.ext_rcv.ccp = fchdr.rsvd; 6948 } 6949 6950 /* pass xrip to FCT in the iocbq */ 6951 iocbq->sbp = xrip; 6952 6953 (void) emlxs_fct_handle_unsol_req(port, cp, iocbq, 6954 seq_mp, seq_len); 6955 break; 6956 #endif /* SFCT_SUPPORT */ 6957 6958 case 0x20: /* CT */ 6959 if (!(port->vpip->flag & EMLXS_VPI_PORT_ENABLED) && 6960 !(hba->flag & FC_LOOPBACK_MODE)) { 6961 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6962 "RQ ENTRY: %s: Port not yet enabled. " 6963 "Dropping...", 6964 label); 6965 6966 goto done; 6967 } 6968 6969 if (!node) { 6970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6971 "RQ ENTRY: %s: Node not found (did=%x). " 6972 "Dropping...", 6973 label, fchdr.d_id); 6974 6975 goto done; 6976 } 6977 6978 rpip = EMLXS_NODE_TO_RPI(port, node); 6979 6980 if (!rpip) { 6981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6982 "RQ ENTRY: %s: RPI not found (did=%x rpi=%d). " 6983 "Dropping...", 6984 label, fchdr.d_id, node->nlp_Rpi); 6985 6986 goto done; 6987 } 6988 6989 xrip = emlxs_sli4_reserve_xri(port, rpip, 6990 EMLXS_XRI_UNSOL_CT_TYPE, fchdr.ox_id); 6991 6992 if (!xrip) { 6993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6994 "RQ ENTRY: %s: Out of exchange " 6995 "resources. Dropping...", 6996 label); 6997 6998 goto done; 6999 } 7000 7001 /* Build CMD_RCV_SEQ64_CX */ 7002 iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0; 7003 iocb->un.rcvseq64.rcvBde.tus.f.bdeSize = seq_len; 7004 iocb->un.rcvseq64.rcvBde.addrLow = PADDR_LO(seq_mp->phys); 7005 iocb->un.rcvseq64.rcvBde.addrHigh = PADDR_HI(seq_mp->phys); 7006 iocb->ULPBDECOUNT = 1; 7007 7008 iocb->un.rcvseq64.xrsqRo = 0; 7009 iocb->un.rcvseq64.w5.hcsw.Rctl = fchdr.r_ctl; 7010 iocb->un.rcvseq64.w5.hcsw.Type = fchdr.type; 7011 iocb->un.rcvseq64.w5.hcsw.Dfctl = fchdr.df_ctl; 7012 iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl; 7013 7014 iocb->ULPPU = 0x3; 7015 iocb->ULPCONTEXT = xrip->XRI; 7016 iocb->ULPIOTAG = rpip->RPI; 7017 iocb->ULPCLASS = CLASS3; 7018 iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX; 7019 7020 iocb->unsli3.ext_rcv.seq_len = seq_len; 7021 iocb->unsli3.ext_rcv.vpi = port->vpip->VPI; 7022 7023 if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { 7024 iocb->unsli3.ext_rcv.ccpe = 1; 7025 iocb->unsli3.ext_rcv.ccp = fchdr.rsvd; 7026 } 7027 7028 (void) emlxs_ct_handle_unsol_req(port, iocbq->channel, 7029 iocbq, seq_mp, seq_len); 7030 7031 break; 7032 } 7033 7034 /* Sequence handled, no need to abort */ 7035 abort = 0; 7036 7037 done: 7038 7039 if (!posted) { 7040 emlxs_sli4_rq_post(port, hdr_rq->qid); 7041 } 7042 7043 if (abort) { 7044 /* Send ABTS for this exchange */ 7045 /* !!! Currently, we have no implementation for this !!! */ 7046 abort = 0; 7047 } 7048 7049 /* Return memory resources to pools */ 7050 if (iocbq) { 7051 if (iocbq->bp) { 7052 emlxs_mem_put(hba, buf_type, (void *)iocbq->bp); 7053 iocbq->bp = 0; 7054 } 7055 7056 emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 7057 } 7058 7059 #ifdef FMA_SUPPORT 7060 if (emlxs_fm_check_dma_handle(hba, 7061 hba->sli.sli4.slim2.dma_handle) 7062 != DDI_FM_OK) { 7063 EMLXS_MSGF(EMLXS_CONTEXT, 7064 &emlxs_invalid_dma_handle_msg, 7065 "sli4_process_unsol_rcv: hdl=%p", 7066 hba->sli.sli4.slim2.dma_handle); 7067 7068 emlxs_thread_spawn(hba, emlxs_restart_thread, 7069 0, 0); 7070 } 7071 #endif 7072 return; 7073 7074 } /* emlxs_sli4_process_unsol_rcv() */ 7075 7076 7077 /*ARGSUSED*/ 7078 static void 7079 emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq, 7080 CQE_XRI_Abort_t *cqe) 7081 { 7082 emlxs_port_t *port = &PPORT; 7083 XRIobj_t *xrip; 7084 7085 mutex_enter(&EMLXS_FCTAB_LOCK); 7086 7087 xrip = emlxs_sli4_find_xri(port, cqe->XRI); 7088 if (xrip == NULL) { 7089 /* EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, */ 7090 /* "CQ ENTRY: process xri aborted ignored"); */ 7091 7092 mutex_exit(&EMLXS_FCTAB_LOCK); 7093 return; 7094 } 7095 7096 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7097 "CQ ENTRY: XRI Aborted: xri=%d IA=%d EO=%d BR=%d", 7098 cqe->XRI, cqe->IA, cqe->EO, cqe->BR); 7099 7100 if (!(xrip->flag & EMLXS_XRI_BUSY)) { 7101 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 7102 "CQ ENTRY: XRI Aborted: xri=%d flag=%x. Bad state.", 7103 xrip->XRI, xrip->flag); 7104 7105 mutex_exit(&EMLXS_FCTAB_LOCK); 7106 return; 7107 } 7108 7109 /* Exchange is no longer busy on-chip, free it */ 7110 emlxs_sli4_free_xri(port, 0, xrip, 0); 7111 7112 mutex_exit(&EMLXS_FCTAB_LOCK); 7113 7114 return; 7115 7116 } /* emlxs_sli4_process_xri_aborted () */ 7117 7118 7119 /*ARGSUSED*/ 7120 static void 7121 emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq) 7122 { 7123 emlxs_port_t *port = &PPORT; 7124 CQE_u *cqe; 7125 CQE_u cq_entry; 7126 int num_entries = 0; 7127 off_t offset; 7128 7129 /* EMLXS_PORT_LOCK must be held when entering this routine */ 7130 7131 cqe = (CQE_u *)cq->addr.virt; 7132 cqe += cq->host_index; 7133 7134 offset = (off_t)((uint64_t)((unsigned long) 7135 cq->addr.virt) - 7136 (uint64_t)((unsigned long) 7137 hba->sli.sli4.slim2.virt)); 7138 7139 EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset, 7140 4096, DDI_DMA_SYNC_FORKERNEL); 7141 7142 for (;;) { 7143 cq_entry.word[3] = BE_SWAP32(cqe->word[3]); 7144 if (((cq_entry.word[3]>>31) & 0x01) != cq->qe_valid) { 7145 #ifdef DEBUG_CQE 7146 if (num_entries == 0) { 7147 EMLXS_MSGF(EMLXS_CONTEXT, 7148 &emlxs_sli_detail_msg, "CQE: Invalid CQE:" 7149 " eqid=%x cqid=%x cqe=%p %08x %08x %08x" 7150 " %08x. host_index=%x valid=%d Break...", 7151 cq->eqid, cq->qid, cqe, 7152 cqe->word[0], cqe->word[1], 7153 cqe->word[2], cqe->word[3], 7154 cq->host_index, cq->qe_valid); 7155 } 7156 #endif /* DEBUG_CQE */ 7157 break; 7158 } 7159 7160 cq_entry.word[2] = BE_SWAP32(cqe->word[2]); 7161 cq_entry.word[1] = BE_SWAP32(cqe->word[1]); 7162 cq_entry.word[0] = BE_SWAP32(cqe->word[0]); 7163 7164 #ifdef DEBUG_CQE 7165 emlxs_data_dump(port, "CQE", (uint32_t *)cqe, 6, 0); 7166 #endif /* DEBUG_CQE */ 7167 num_entries++; 7168 if (hba->sli.sli4.param.CqAV) 7169 /* do not attach the valid bit */ 7170 cqe->word[3] &= BE_SWAP32(CQE_VALID); 7171 else 7172 cqe->word[3] = 0; 7173 7174 cq->host_index++; 7175 if (cq->host_index >= cq->max_index) { 7176 cq->host_index = 0; 7177 cqe = (CQE_u *)cq->addr.virt; 7178 if (hba->sli.sli4.param.CqAV) 7179 cq->qe_valid ^= 1; 7180 } else { 7181 cqe++; 7182 } 7183 mutex_exit(&EMLXS_PORT_LOCK); 7184 7185 /* Now handle specific cq type */ 7186 if (cq->type == EMLXS_CQ_TYPE_GROUP1) { 7187 if (cq_entry.cqAsyncEntry.async_evt) { 7188 emlxs_sli4_process_async_event(hba, 7189 (CQE_ASYNC_t *)&cq_entry); 7190 } else { 7191 emlxs_sli4_process_mbox_event(hba, 7192 (CQE_MBOX_t *)&cq_entry); 7193 } 7194 } else { /* EMLXS_CQ_TYPE_GROUP2 */ 7195 switch (cq_entry.cqCmplEntry.Code) { 7196 case CQE_TYPE_WQ_COMPLETION: 7197 if (cq_entry.cqCmplEntry.RequestTag < 7198 hba->max_iotag) { 7199 emlxs_sli4_process_wqe_cmpl(hba, cq, 7200 (CQE_CmplWQ_t *)&cq_entry); 7201 } else { 7202 emlxs_sli4_process_oor_wqe_cmpl(hba, cq, 7203 (CQE_CmplWQ_t *)&cq_entry); 7204 } 7205 break; 7206 case CQE_TYPE_RELEASE_WQE: 7207 emlxs_sli4_process_release_wqe(hba, cq, 7208 (CQE_RelWQ_t *)&cq_entry); 7209 break; 7210 case CQE_TYPE_UNSOL_RCV: 7211 case CQE_TYPE_UNSOL_RCV_V1: 7212 emlxs_sli4_process_unsol_rcv(hba, cq, 7213 (CQE_UnsolRcv_t *)&cq_entry); 7214 break; 7215 case CQE_TYPE_XRI_ABORTED: 7216 emlxs_sli4_process_xri_aborted(hba, cq, 7217 (CQE_XRI_Abort_t *)&cq_entry); 7218 break; 7219 default: 7220 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 7221 "Invalid CQ entry eqid=%x qid=%x code=%d: " 7222 "%08x %08x %08x %08x, host_index=%x " 7223 "valid=%d", 7224 cq->eqid, cq->qid, 7225 cq_entry.cqCmplEntry.Code, cq_entry.word[0], 7226 cq_entry.word[1], cq_entry.word[2], 7227 cq_entry.word[3], cq->host_index, 7228 cq->qe_valid); 7229 break; 7230 } 7231 } 7232 7233 mutex_enter(&EMLXS_PORT_LOCK); 7234 } 7235 7236 /* Number of times this routine gets called for this CQ */ 7237 cq->isr_count++; 7238 7239 /* num_entries is the number of CQEs we process in this specific CQ */ 7240 cq->num_proc += num_entries; 7241 if (cq->max_proc < num_entries) 7242 cq->max_proc = num_entries; 7243 7244 emlxs_sli4_write_cqdb(hba, cq->qid, num_entries, B_TRUE); 7245 7246 /* EMLXS_PORT_LOCK must be held when exiting this routine */ 7247 7248 } /* emlxs_sli4_process_cq() */ 7249 7250 7251 /*ARGSUSED*/ 7252 static void 7253 emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) 7254 { 7255 emlxs_port_t *port = &PPORT; 7256 uint32_t *ptr; 7257 CHANNEL *cp; 7258 EQE_u eqe; 7259 uint32_t i; 7260 uint16_t cqi; 7261 int num_entries = 0; 7262 off_t offset; 7263 7264 /* EMLXS_PORT_LOCK must be held when entering this routine */ 7265 7266 hba->intr_busy_cnt ++; 7267 7268 ptr = eq->addr.virt; 7269 ptr += eq->host_index; 7270 7271 offset = (off_t)((uint64_t)((unsigned long) 7272 eq->addr.virt) - 7273 (uint64_t)((unsigned long) 7274 hba->sli.sli4.slim2.virt)); 7275 7276 EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset, 7277 4096, DDI_DMA_SYNC_FORKERNEL); 7278 7279 for (;;) { 7280 eqe.word = *ptr; 7281 eqe.word = BE_SWAP32(eqe.word); 7282 7283 if ((eqe.word & EQE_VALID) != eq->qe_valid) { 7284 #ifdef DEBUG_FASTPATH 7285 if (num_entries == 0) { 7286 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7287 "EQE: Invalid EQE: %x. host_index=%x " 7288 "valid=%d Break...", 7289 eqe.word, eq->qe_valid); 7290 } 7291 #endif /* DEBUG_FASTPATH */ 7292 break; 7293 } 7294 7295 #ifdef DEBUG_FASTPATH 7296 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7297 "EQE00: %08x", eqe.word); 7298 #endif /* DEBUG_FASTPATH */ 7299 7300 if (hba->sli.sli4.param.EqAV) 7301 *ptr &= BE_SWAP32(EQE_VALID); 7302 else 7303 *ptr = 0; 7304 num_entries++; 7305 eq->host_index++; 7306 if (eq->host_index >= eq->max_index) { 7307 eq->host_index = 0; 7308 ptr = eq->addr.virt; 7309 if (hba->sli.sli4.param.EqAV) 7310 eq->qe_valid ^= 1; 7311 } else { 7312 ptr++; 7313 } 7314 7315 cqi = emlxs_sli4_cqid_to_index(hba, eqe.entry.CQId); 7316 7317 /* Verify CQ index */ 7318 if (cqi == 0xffff) { 7319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 7320 "EQE: Invalid CQid: %d. valid=%d Dropping...", 7321 eqe.entry.CQId, eq->qe_valid); 7322 continue; 7323 } 7324 7325 #ifdef DEBUG_FASTPATH 7326 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7327 "EQE: qid=%x host_index=%x valid=%d iptr=%p CQIndex:%x " 7328 "cqid:%x", 7329 eq->qid, eq->host_index, eq->qe_valid, ptr, cqi, 7330 eqe.entry.CQId); 7331 #endif /* DEBUG_FASTPATH */ 7332 7333 emlxs_sli4_process_cq(hba, &hba->sli.sli4.cq[cqi]); 7334 } 7335 7336 /* Number of times the ISR for this EQ gets called */ 7337 eq->isr_count++; 7338 7339 /* num_entries is the number of EQEs we process in this specific ISR */ 7340 eq->num_proc += num_entries; 7341 if (eq->max_proc < num_entries) { 7342 eq->max_proc = num_entries; 7343 } 7344 7345 if (num_entries != 0) { 7346 for (i = 0; i < hba->chan_count; i++) { 7347 cp = &hba->chan[i]; 7348 if (cp->chan_flag & EMLXS_NEEDS_TRIGGER) { 7349 cp->chan_flag &= ~EMLXS_NEEDS_TRIGGER; 7350 emlxs_thread_trigger2(&cp->intr_thread, 7351 emlxs_proc_channel, cp); 7352 } 7353 } 7354 } 7355 7356 emlxs_sli4_write_eqdb(hba, eq->qid, num_entries, B_TRUE); 7357 7358 /* EMLXS_PORT_LOCK must be held when exiting this routine */ 7359 7360 hba->intr_busy_cnt --; 7361 7362 } /* emlxs_sli4_process_eq() */ 7363 7364 7365 #ifdef MSI_SUPPORT 7366 /*ARGSUSED*/ 7367 static uint32_t 7368 emlxs_sli4_msi_intr(char *arg1, char *arg2) 7369 { 7370 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 7371 #ifdef DEBUG_FASTPATH 7372 emlxs_port_t *port = &PPORT; 7373 #endif /* DEBUG_FASTPATH */ 7374 uint16_t msgid; 7375 int rc; 7376 7377 #ifdef DEBUG_FASTPATH 7378 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7379 "msiINTR arg1:%p arg2:%p", arg1, arg2); 7380 #endif /* DEBUG_FASTPATH */ 7381 7382 /* Check for legacy interrupt handling */ 7383 if (hba->intr_type == DDI_INTR_TYPE_FIXED) { 7384 rc = emlxs_sli4_intx_intr(arg1); 7385 return (rc); 7386 } 7387 7388 /* Get MSI message id */ 7389 msgid = (uint16_t)((unsigned long)arg2); 7390 7391 /* Validate the message id */ 7392 if (msgid >= hba->intr_count) { 7393 msgid = 0; 7394 } 7395 mutex_enter(&EMLXS_PORT_LOCK); 7396 7397 if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) { 7398 mutex_exit(&EMLXS_PORT_LOCK); 7399 return (DDI_INTR_UNCLAIMED); 7400 } 7401 7402 /* The eq[] index == the MSI vector number */ 7403 emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]); 7404 7405 mutex_exit(&EMLXS_PORT_LOCK); 7406 return (DDI_INTR_CLAIMED); 7407 7408 } /* emlxs_sli4_msi_intr() */ 7409 #endif /* MSI_SUPPORT */ 7410 7411 7412 /*ARGSUSED*/ 7413 static int 7414 emlxs_sli4_intx_intr(char *arg) 7415 { 7416 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 7417 #ifdef DEBUG_FASTPATH 7418 emlxs_port_t *port = &PPORT; 7419 #endif /* DEBUG_FASTPATH */ 7420 7421 #ifdef DEBUG_FASTPATH 7422 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7423 "intxINTR arg:%p", arg); 7424 #endif /* DEBUG_FASTPATH */ 7425 7426 mutex_enter(&EMLXS_PORT_LOCK); 7427 7428 if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) { 7429 mutex_exit(&EMLXS_PORT_LOCK); 7430 return (DDI_INTR_UNCLAIMED); 7431 } 7432 7433 emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[0]); 7434 7435 mutex_exit(&EMLXS_PORT_LOCK); 7436 return (DDI_INTR_CLAIMED); 7437 } /* emlxs_sli4_intx_intr() */ 7438 7439 7440 static void 7441 emlxs_sli4_hba_kill(emlxs_hba_t *hba) 7442 { 7443 emlxs_port_t *port = &PPORT; 7444 uint32_t j; 7445 7446 mutex_enter(&EMLXS_PORT_LOCK); 7447 if (hba->flag & FC_INTERLOCKED) { 7448 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 7449 7450 mutex_exit(&EMLXS_PORT_LOCK); 7451 7452 return; 7453 } 7454 7455 j = 0; 7456 while (j++ < 10000) { 7457 if ((hba->mbox_queue_flag == 0) && 7458 (hba->intr_busy_cnt == 0)) { 7459 break; 7460 } 7461 7462 mutex_exit(&EMLXS_PORT_LOCK); 7463 BUSYWAIT_US(100); 7464 mutex_enter(&EMLXS_PORT_LOCK); 7465 } 7466 7467 if ((hba->mbox_queue_flag != 0) || (hba->intr_busy_cnt > 0)) { 7468 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 7469 "Board kill failed. Adapter busy, %d, %d.", 7470 hba->mbox_queue_flag, hba->intr_busy_cnt); 7471 mutex_exit(&EMLXS_PORT_LOCK); 7472 return; 7473 } 7474 7475 hba->flag |= FC_INTERLOCKED; 7476 7477 EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 7478 7479 mutex_exit(&EMLXS_PORT_LOCK); 7480 7481 } /* emlxs_sli4_hba_kill() */ 7482 7483 7484 extern void 7485 emlxs_sli4_hba_reset_all(emlxs_hba_t *hba, uint32_t flag) 7486 { 7487 emlxs_port_t *port = &PPORT; 7488 uint32_t value; 7489 7490 mutex_enter(&EMLXS_PORT_LOCK); 7491 7492 if ((hba->sli_intf & SLI_INTF_IF_TYPE_MASK) != SLI_INTF_IF_TYPE_2 && 7493 (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) != SLI_INTF_IF_TYPE_6) { 7494 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 7495 "Reset All failed. Invalid Operation."); 7496 mutex_exit(&EMLXS_PORT_LOCK); 7497 return; 7498 } 7499 7500 /* Issue a Firmware Reset All Request */ 7501 if (flag) { 7502 value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL | SLI_PHYDEV_DD; 7503 } else { 7504 value = SLI_PHYDEV_FRST | SLI_PHYDEV_FRL_ALL; 7505 } 7506 7507 ddi_put32(hba->sli.sli4.bar0_acc_handle, 7508 hba->sli.sli4.PHYSDEV_reg_addr, value); 7509 7510 mutex_exit(&EMLXS_PORT_LOCK); 7511 7512 } /* emlxs_sli4_hba_reset_all() */ 7513 7514 7515 static void 7516 emlxs_sli4_enable_intr(emlxs_hba_t *hba) 7517 { 7518 emlxs_config_t *cfg = &CFG; 7519 int i; 7520 int num_cq; 7521 7522 hba->sli.sli4.flag |= EMLXS_SLI4_INTR_ENABLED; 7523 7524 num_cq = (hba->intr_count * cfg[CFG_NUM_WQ].current) + 7525 EMLXS_CQ_OFFSET_WQ; 7526 7527 /* ARM EQ / CQs */ 7528 for (i = 0; i < num_cq; i++) { 7529 emlxs_sli4_write_cqdb(hba, hba->sli.sli4.cq[i].qid, 0, B_TRUE); 7530 } 7531 7532 for (i = 0; i < hba->intr_count; i++) { 7533 emlxs_sli4_write_eqdb(hba, hba->sli.sli4.eq[i].qid, 0, B_TRUE); 7534 } 7535 } /* emlxs_sli4_enable_intr() */ 7536 7537 7538 static void 7539 emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att) 7540 { 7541 if (att) { 7542 return; 7543 } 7544 7545 hba->sli.sli4.flag &= ~EMLXS_SLI4_INTR_ENABLED; 7546 7547 /* Short of reset, we cannot disable interrupts */ 7548 } /* emlxs_sli4_disable_intr() */ 7549 7550 static void 7551 emlxs_sli4_resource_free(emlxs_hba_t *hba) 7552 { 7553 emlxs_port_t *port = &PPORT; 7554 MBUF_INFO *buf_info; 7555 uint32_t i; 7556 7557 buf_info = &hba->sli.sli4.slim2; 7558 if (buf_info->virt == 0) { 7559 /* Already free */ 7560 return; 7561 } 7562 7563 emlxs_fcf_fini(hba); 7564 7565 mutex_enter(&EMLXS_PORT_LOCK); 7566 7567 buf_info = &hba->sli.sli4.HeaderTmplate; 7568 if (buf_info->virt) { 7569 bzero(buf_info, sizeof (MBUF_INFO)); 7570 } 7571 7572 if (hba->sli.sli4.XRIp) { 7573 XRIobj_t *xrip; 7574 7575 if ((hba->sli.sli4.XRIinuse_f != 7576 (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) || 7577 (hba->sli.sli4.XRIinuse_b != 7578 (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) { 7579 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; 7580 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { 7581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 7582 "XRIs in use during free!: %p %p != %p " 7583 "XRI:%d iotag:%d\n", 7584 hba->sli.sli4.XRIinuse_f, 7585 hba->sli.sli4.XRIinuse_b, xrip, xrip->XRI, 7586 xrip->iotag); 7587 xrip = xrip->_f; 7588 } 7589 } 7590 7591 xrip = hba->sli.sli4.XRIp; 7592 for (i = 0; i < hba->sli.sli4.XRICount; i++) { 7593 xrip->XRI = emlxs_sli4_index_to_xri(hba, i); 7594 7595 if (xrip->XRI != 0) 7596 emlxs_mem_put(hba, xrip->SGSeg, xrip->SGList); 7597 7598 xrip++; 7599 } 7600 7601 kmem_free(hba->sli.sli4.XRIp, 7602 (sizeof (XRIobj_t) * hba->sli.sli4.XRICount)); 7603 hba->sli.sli4.XRIp = NULL; 7604 7605 hba->sli.sli4.XRIfree_f = 7606 (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 7607 hba->sli.sli4.XRIfree_b = 7608 (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 7609 hba->sli.sli4.xrif_count = 0; 7610 } 7611 7612 for (i = 0; i < hba->intr_count; i++) { 7613 mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock); 7614 bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t)); 7615 hba->sli.sli4.eq[i].qid = 0xffff; 7616 } 7617 for (i = 0; i < EMLXS_MAX_CQS; i++) { 7618 bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t)); 7619 hba->sli.sli4.cq[i].qid = 0xffff; 7620 } 7621 for (i = 0; i < EMLXS_MAX_WQS; i++) { 7622 bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t)); 7623 hba->sli.sli4.wq[i].qid = 0xffff; 7624 } 7625 for (i = 0; i < EMLXS_MAX_RXQS; i++) { 7626 mutex_destroy(&hba->sli.sli4.rxq[i].lock); 7627 bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t)); 7628 } 7629 for (i = 0; i < EMLXS_MAX_RQS; i++) { 7630 mutex_destroy(&hba->sli.sli4.rq[i].lock); 7631 bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t)); 7632 hba->sli.sli4.rq[i].qid = 0xffff; 7633 } 7634 7635 /* Free the MQ */ 7636 bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); 7637 7638 7639 buf_info = &hba->sli.sli4.slim2; 7640 if (buf_info->virt) { 7641 buf_info->flags = FC_MBUF_DMA; 7642 emlxs_mem_free(hba, buf_info); 7643 bzero(buf_info, sizeof (MBUF_INFO)); 7644 } 7645 7646 mutex_exit(&EMLXS_PORT_LOCK); 7647 7648 /* GPIO lock */ 7649 if (hba->model_info.flags & EMLXS_GPIO_LEDS) 7650 mutex_destroy(&hba->gpio_lock); 7651 7652 7653 } /* emlxs_sli4_resource_free() */ 7654 7655 static int 7656 emlxs_sli4_resource_alloc(emlxs_hba_t *hba) 7657 { 7658 emlxs_port_t *port = &PPORT; 7659 emlxs_config_t *cfg = &CFG; 7660 MBUF_INFO *buf_info; 7661 int num_eq; 7662 int num_wq; 7663 uint16_t i; 7664 uint32_t j; 7665 uint32_t k; 7666 uint16_t cq_depth; 7667 uint32_t cq_size; 7668 uint32_t word; 7669 XRIobj_t *xrip; 7670 RQE_t *rqe; 7671 MBUF_INFO *rqb; 7672 uint64_t phys; 7673 uint64_t tmp_phys; 7674 char *virt; 7675 char *tmp_virt; 7676 void *data_handle; 7677 void *dma_handle; 7678 int32_t size; 7679 off_t offset; 7680 uint32_t count = 0; 7681 uint32_t hddr_size = 0; 7682 uint32_t align; 7683 uint32_t iotag; 7684 uint32_t mseg; 7685 7686 buf_info = &hba->sli.sli4.slim2; 7687 if (buf_info->virt) { 7688 /* Already allocated */ 7689 return (0); 7690 } 7691 7692 emlxs_fcf_init(hba); 7693 7694 switch (hba->sli.sli4.param.CQV) { 7695 case 0: 7696 cq_depth = CQ_DEPTH; 7697 break; 7698 case 2: 7699 default: 7700 cq_depth = CQ_DEPTH_V2; 7701 break; 7702 } 7703 cq_size = (cq_depth * CQE_SIZE); 7704 7705 /* EQs - 1 per Interrupt vector */ 7706 num_eq = hba->intr_count; 7707 7708 /* CQs - number of WQs + 1 for RQs + 1 for mbox/async events */ 7709 num_wq = cfg[CFG_NUM_WQ].current * num_eq; 7710 7711 /* Calculate total dmable memory we need */ 7712 /* WARNING: make sure each section is aligned on 4K boundary */ 7713 7714 /* EQ */ 7715 count += num_eq * 4096; 7716 7717 /* CQ */ 7718 count += (num_wq + EMLXS_CQ_OFFSET_WQ) * cq_size; 7719 7720 /* WQ */ 7721 count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES); 7722 7723 /* MQ */ 7724 count += EMLXS_MAX_MQS * 4096; 7725 7726 /* RQ */ 7727 count += EMLXS_MAX_RQS * 4096; 7728 7729 /* RQB/E */ 7730 count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE); 7731 count += (4096 - (count%4096)); /* Ensure 4K alignment */ 7732 7733 /* RPI Header Templates */ 7734 if (hba->sli.sli4.param.HDRR) { 7735 /* Bytes per extent */ 7736 j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t); 7737 7738 /* Pages required per extent (page == 4096 bytes) */ 7739 k = (j/4096) + ((j%4096)? 1:0); 7740 7741 /* Total size */ 7742 hddr_size = (k * hba->sli.sli4.RPIExtCount * 4096); 7743 7744 count += hddr_size; 7745 } 7746 7747 /* Allocate slim2 for SLI4 */ 7748 buf_info = &hba->sli.sli4.slim2; 7749 buf_info->size = count; 7750 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7751 buf_info->align = ddi_ptob(hba->dip, 1L); 7752 7753 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 7754 "Allocating memory for slim2: %d", count); 7755 7756 (void) emlxs_mem_alloc(hba, buf_info); 7757 7758 if (buf_info->virt == NULL) { 7759 EMLXS_MSGF(EMLXS_CONTEXT, 7760 &emlxs_init_failed_msg, 7761 "Unable to allocate internal memory for SLI4: %d", 7762 count); 7763 goto failed; 7764 } 7765 bzero(buf_info->virt, buf_info->size); 7766 EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0, 7767 buf_info->size, DDI_DMA_SYNC_FORDEV); 7768 7769 /* Assign memory to Head Template, EQ, CQ, WQ, RQ and MQ */ 7770 data_handle = buf_info->data_handle; 7771 dma_handle = buf_info->dma_handle; 7772 phys = buf_info->phys; 7773 virt = (char *)buf_info->virt; 7774 7775 /* Allocate space for queues */ 7776 7777 /* EQ */ 7778 size = 4096; 7779 for (i = 0; i < num_eq; i++) { 7780 bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t)); 7781 7782 buf_info = &hba->sli.sli4.eq[i].addr; 7783 buf_info->size = size; 7784 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7785 buf_info->align = ddi_ptob(hba->dip, 1L); 7786 buf_info->phys = phys; 7787 buf_info->virt = (void *)virt; 7788 buf_info->data_handle = data_handle; 7789 buf_info->dma_handle = dma_handle; 7790 7791 phys += size; 7792 virt += size; 7793 7794 hba->sli.sli4.eq[i].max_index = EQ_DEPTH; 7795 hba->sli.sli4.eq[i].qid = 0xffff; 7796 7797 mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, NULL, 7798 MUTEX_DRIVER, NULL); 7799 hba->sli.sli4.eq[i].qe_valid = 1; 7800 } 7801 7802 7803 /* CQ */ 7804 for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) { 7805 bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t)); 7806 7807 buf_info = &hba->sli.sli4.cq[i].addr; 7808 buf_info->size = cq_size; 7809 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7810 buf_info->align = ddi_ptob(hba->dip, 1L); 7811 buf_info->phys = phys; 7812 buf_info->virt = (void *)virt; 7813 buf_info->data_handle = data_handle; 7814 buf_info->dma_handle = dma_handle; 7815 7816 phys += cq_size; 7817 virt += cq_size; 7818 7819 hba->sli.sli4.cq[i].max_index = cq_depth; 7820 hba->sli.sli4.cq[i].qid = 0xffff; 7821 hba->sli.sli4.cq[i].qe_valid = 1; 7822 } 7823 7824 7825 /* WQ */ 7826 size = 4096 * EMLXS_NUM_WQ_PAGES; 7827 for (i = 0; i < num_wq; i++) { 7828 bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t)); 7829 7830 buf_info = &hba->sli.sli4.wq[i].addr; 7831 buf_info->size = size; 7832 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7833 buf_info->align = ddi_ptob(hba->dip, 1L); 7834 buf_info->phys = phys; 7835 buf_info->virt = (void *)virt; 7836 buf_info->data_handle = data_handle; 7837 buf_info->dma_handle = dma_handle; 7838 7839 phys += size; 7840 virt += size; 7841 7842 hba->sli.sli4.wq[i].max_index = WQ_DEPTH; 7843 hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH; 7844 hba->sli.sli4.wq[i].qid = 0xFFFF; 7845 } 7846 7847 7848 /* MQ */ 7849 size = 4096; 7850 bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); 7851 7852 buf_info = &hba->sli.sli4.mq.addr; 7853 buf_info->size = size; 7854 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7855 buf_info->align = ddi_ptob(hba->dip, 1L); 7856 buf_info->phys = phys; 7857 buf_info->virt = (void *)virt; 7858 buf_info->data_handle = data_handle; 7859 buf_info->dma_handle = dma_handle; 7860 7861 phys += size; 7862 virt += size; 7863 7864 hba->sli.sli4.mq.max_index = MQ_DEPTH; 7865 7866 7867 /* RXQ */ 7868 for (i = 0; i < EMLXS_MAX_RXQS; i++) { 7869 bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t)); 7870 7871 mutex_init(&hba->sli.sli4.rxq[i].lock, NULL, MUTEX_DRIVER, 7872 NULL); 7873 } 7874 7875 7876 /* RQ */ 7877 size = 4096; 7878 for (i = 0; i < EMLXS_MAX_RQS; i++) { 7879 bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t)); 7880 7881 buf_info = &hba->sli.sli4.rq[i].addr; 7882 buf_info->size = size; 7883 buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7884 buf_info->align = ddi_ptob(hba->dip, 1L); 7885 buf_info->phys = phys; 7886 buf_info->virt = (void *)virt; 7887 buf_info->data_handle = data_handle; 7888 buf_info->dma_handle = dma_handle; 7889 7890 phys += size; 7891 virt += size; 7892 7893 hba->sli.sli4.rq[i].max_index = RQ_DEPTH; 7894 hba->sli.sli4.rq[i].qid = 0xFFFF; 7895 7896 mutex_init(&hba->sli.sli4.rq[i].lock, NULL, MUTEX_DRIVER, NULL); 7897 } 7898 7899 7900 /* RQB/E */ 7901 for (i = 0; i < EMLXS_MAX_RQS; i++) { 7902 size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE; 7903 tmp_phys = phys; 7904 tmp_virt = virt; 7905 7906 /* Initialize the RQEs */ 7907 rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt; 7908 for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) { 7909 phys = tmp_phys; 7910 virt = tmp_virt; 7911 for (k = 0; k < RQB_COUNT; k++) { 7912 word = PADDR_HI(phys); 7913 rqe->AddrHi = BE_SWAP32(word); 7914 7915 word = PADDR_LO(phys); 7916 rqe->AddrLo = BE_SWAP32(word); 7917 7918 rqb = &hba->sli.sli4.rq[i]. 7919 rqb[k + (j * RQB_COUNT)]; 7920 rqb->size = size; 7921 rqb->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG; 7922 rqb->align = ddi_ptob(hba->dip, 1L); 7923 rqb->phys = phys; 7924 rqb->virt = (void *)virt; 7925 rqb->data_handle = data_handle; 7926 rqb->dma_handle = dma_handle; 7927 7928 phys += size; 7929 virt += size; 7930 #ifdef DEBUG_RQE 7931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7932 "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p flags=%d", 7933 i, j, k, rqb, rqb->flags); 7934 #endif /* DEBUG_RQE */ 7935 7936 rqe++; 7937 } 7938 } 7939 7940 offset = (off_t)((uint64_t)((unsigned long) 7941 hba->sli.sli4.rq[i].addr.virt) - 7942 (uint64_t)((unsigned long) 7943 hba->sli.sli4.slim2.virt)); 7944 7945 /* Sync the RQ buffer list */ 7946 EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset, 7947 hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV); 7948 } 7949 7950 /* 4K Alignment */ 7951 align = (4096 - (phys%4096)); 7952 phys += align; 7953 virt += align; 7954 7955 /* RPI Header Templates */ 7956 if (hba->sli.sli4.param.HDRR) { 7957 buf_info = &hba->sli.sli4.HeaderTmplate; 7958 bzero(buf_info, sizeof (MBUF_INFO)); 7959 buf_info->size = hddr_size; 7960 buf_info->flags = FC_MBUF_DMA; 7961 buf_info->align = ddi_ptob(hba->dip, 1L); 7962 buf_info->phys = phys; 7963 buf_info->virt = (void *)virt; 7964 buf_info->data_handle = data_handle; 7965 buf_info->dma_handle = dma_handle; 7966 } 7967 7968 /* SGL */ 7969 7970 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 7971 "Allocating memory for %d SGLs: %d/%d", 7972 hba->sli.sli4.XRICount, sizeof (XRIobj_t), size); 7973 7974 /* Initialize double linked lists */ 7975 hba->sli.sli4.XRIinuse_f = 7976 (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; 7977 hba->sli.sli4.XRIinuse_b = 7978 (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; 7979 hba->sli.sli4.xria_count = 0; 7980 7981 hba->sli.sli4.XRIfree_f = 7982 (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 7983 hba->sli.sli4.XRIfree_b = 7984 (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 7985 hba->sli.sli4.xrif_count = 0; 7986 7987 switch (hba->sli.sli4.mem_sgl_size) { 7988 case 1024: 7989 mseg = MEM_SGL1K; 7990 break; 7991 case 2048: 7992 mseg = MEM_SGL2K; 7993 break; 7994 case 4096: 7995 mseg = MEM_SGL4K; 7996 break; 7997 default: 7998 EMLXS_MSGF(EMLXS_CONTEXT, 7999 &emlxs_init_failed_msg, 8000 "Unsupported SGL Size: %d", hba->sli.sli4.mem_sgl_size); 8001 goto failed; 8002 } 8003 8004 hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc( 8005 (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP); 8006 8007 xrip = hba->sli.sli4.XRIp; 8008 iotag = 1; 8009 8010 for (i = 0; i < hba->sli.sli4.XRICount; i++) { 8011 xrip->XRI = emlxs_sli4_index_to_xri(hba, i); 8012 8013 /* We don't use XRI==0, since it also represents an */ 8014 /* uninitialized exchange */ 8015 if (xrip->XRI == 0) { 8016 xrip++; 8017 continue; 8018 } 8019 8020 xrip->iotag = iotag++; 8021 xrip->sge_count = 8022 (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64)); 8023 8024 /* Add xrip to end of free list */ 8025 xrip->_b = hba->sli.sli4.XRIfree_b; 8026 hba->sli.sli4.XRIfree_b->_f = xrip; 8027 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 8028 hba->sli.sli4.XRIfree_b = xrip; 8029 hba->sli.sli4.xrif_count++; 8030 8031 /* Allocate SGL for this xrip */ 8032 xrip->SGSeg = mseg; 8033 xrip->SGList = emlxs_mem_get(hba, xrip->SGSeg); 8034 8035 if (xrip->SGList == NULL) { 8036 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 8037 "Unable to allocate memory for SGL %d", i); 8038 goto failed; 8039 } 8040 8041 EMLXS_MPDATA_SYNC(xrip->SGList->dma_handle, 0, 8042 xrip->SGList->size, DDI_DMA_SYNC_FORDEV); 8043 8044 xrip++; 8045 } 8046 8047 /* GPIO lock */ 8048 if (hba->model_info.flags & EMLXS_GPIO_LEDS) 8049 mutex_init(&hba->gpio_lock, NULL, MUTEX_DRIVER, NULL); 8050 8051 #ifdef FMA_SUPPORT 8052 if (hba->sli.sli4.slim2.dma_handle) { 8053 if (emlxs_fm_check_dma_handle(hba, 8054 hba->sli.sli4.slim2.dma_handle) 8055 != DDI_FM_OK) { 8056 EMLXS_MSGF(EMLXS_CONTEXT, 8057 &emlxs_invalid_dma_handle_msg, 8058 "sli4_resource_alloc: hdl=%p", 8059 hba->sli.sli4.slim2.dma_handle); 8060 goto failed; 8061 } 8062 } 8063 #endif /* FMA_SUPPORT */ 8064 8065 return (0); 8066 8067 failed: 8068 8069 (void) emlxs_sli4_resource_free(hba); 8070 return (ENOMEM); 8071 8072 } /* emlxs_sli4_resource_alloc */ 8073 8074 8075 extern void 8076 emlxs_sli4_zero_queue_stat(emlxs_hba_t *hba) 8077 { 8078 uint32_t i; 8079 uint32_t num_wq; 8080 emlxs_config_t *cfg = &CFG; 8081 clock_t time; 8082 8083 /* EQ */ 8084 for (i = 0; i < hba->intr_count; i++) { 8085 hba->sli.sli4.eq[i].num_proc = 0; 8086 hba->sli.sli4.eq[i].max_proc = 0; 8087 hba->sli.sli4.eq[i].isr_count = 0; 8088 } 8089 num_wq = cfg[CFG_NUM_WQ].current * hba->intr_count; 8090 /* CQ */ 8091 for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) { 8092 hba->sli.sli4.cq[i].num_proc = 0; 8093 hba->sli.sli4.cq[i].max_proc = 0; 8094 hba->sli.sli4.cq[i].isr_count = 0; 8095 } 8096 /* WQ */ 8097 for (i = 0; i < num_wq; i++) { 8098 hba->sli.sli4.wq[i].num_proc = 0; 8099 hba->sli.sli4.wq[i].num_busy = 0; 8100 } 8101 /* RQ */ 8102 for (i = 0; i < EMLXS_MAX_RQS; i++) { 8103 hba->sli.sli4.rq[i].num_proc = 0; 8104 } 8105 (void) drv_getparm(LBOLT, &time); 8106 hba->sli.sli4.que_stat_timer = (uint32_t)time; 8107 8108 } /* emlxs_sli4_zero_queue_stat */ 8109 8110 8111 extern XRIobj_t * 8112 emlxs_sli4_reserve_xri(emlxs_port_t *port, RPIobj_t *rpip, uint32_t type, 8113 uint16_t rx_id) 8114 { 8115 emlxs_hba_t *hba = HBA; 8116 XRIobj_t *xrip; 8117 uint16_t iotag; 8118 8119 mutex_enter(&EMLXS_FCTAB_LOCK); 8120 8121 xrip = hba->sli.sli4.XRIfree_f; 8122 8123 if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { 8124 mutex_exit(&EMLXS_FCTAB_LOCK); 8125 8126 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 8127 "Unable to reserve XRI. type=%d", 8128 type); 8129 8130 return (NULL); 8131 } 8132 8133 iotag = xrip->iotag; 8134 8135 if ((!iotag) || 8136 ((hba->fc_table[iotag] != NULL) && 8137 (hba->fc_table[iotag] != STALE_PACKET))) { 8138 /* 8139 * No more command slots available, retry later 8140 */ 8141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8142 "Adapter Busy. Unable to reserve iotag. type=%d", 8143 type); 8144 8145 mutex_exit(&EMLXS_FCTAB_LOCK); 8146 return (NULL); 8147 } 8148 8149 xrip->state = XRI_STATE_ALLOCATED; 8150 xrip->type = type; 8151 xrip->flag = EMLXS_XRI_RESERVED; 8152 xrip->sbp = NULL; 8153 8154 xrip->rpip = rpip; 8155 xrip->rx_id = rx_id; 8156 rpip->xri_count++; 8157 8158 /* Take it off free list */ 8159 (xrip->_b)->_f = xrip->_f; 8160 (xrip->_f)->_b = xrip->_b; 8161 xrip->_f = NULL; 8162 xrip->_b = NULL; 8163 hba->sli.sli4.xrif_count--; 8164 8165 /* Add it to end of inuse list */ 8166 xrip->_b = hba->sli.sli4.XRIinuse_b; 8167 hba->sli.sli4.XRIinuse_b->_f = xrip; 8168 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; 8169 hba->sli.sli4.XRIinuse_b = xrip; 8170 hba->sli.sli4.xria_count++; 8171 8172 mutex_exit(&EMLXS_FCTAB_LOCK); 8173 return (xrip); 8174 8175 } /* emlxs_sli4_reserve_xri() */ 8176 8177 8178 extern uint32_t 8179 emlxs_sli4_unreserve_xri(emlxs_port_t *port, uint16_t xri, uint32_t lock) 8180 { 8181 emlxs_hba_t *hba = HBA; 8182 XRIobj_t *xrip; 8183 8184 if (lock) { 8185 mutex_enter(&EMLXS_FCTAB_LOCK); 8186 } 8187 8188 xrip = emlxs_sli4_find_xri(port, xri); 8189 8190 if (!xrip || xrip->state == XRI_STATE_FREE) { 8191 if (lock) { 8192 mutex_exit(&EMLXS_FCTAB_LOCK); 8193 } 8194 8195 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8196 "sli4_unreserve_xri:%d already freed.", xri); 8197 return (0); 8198 } 8199 8200 /* Flush this unsolicited ct command */ 8201 if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) { 8202 (void) emlxs_flush_ct_event(port, xrip->rx_id); 8203 } 8204 8205 if (!(xrip->flag & EMLXS_XRI_RESERVED)) { 8206 if (lock) { 8207 mutex_exit(&EMLXS_FCTAB_LOCK); 8208 } 8209 8210 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8211 "sli4_unreserve_xri:%d in use. type=%d", 8212 xrip->XRI, xrip->type); 8213 return (1); 8214 } 8215 8216 if (xrip->iotag && 8217 (hba->fc_table[xrip->iotag] != NULL) && 8218 (hba->fc_table[xrip->iotag] != STALE_PACKET)) { 8219 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, 8220 "sli4_unreserve_xri:%d sbp dropped:%p type=%d", 8221 xrip->XRI, hba->fc_table[xrip->iotag], xrip->type); 8222 8223 hba->fc_table[xrip->iotag] = NULL; 8224 hba->io_count--; 8225 } 8226 8227 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8228 "sli4_unreserve_xri:%d unreserved. type=%d", 8229 xrip->XRI, xrip->type); 8230 8231 xrip->state = XRI_STATE_FREE; 8232 xrip->type = 0; 8233 8234 if (xrip->rpip) { 8235 xrip->rpip->xri_count--; 8236 xrip->rpip = NULL; 8237 } 8238 8239 if (xrip->reserved_rpip) { 8240 xrip->reserved_rpip->xri_count--; 8241 xrip->reserved_rpip = NULL; 8242 } 8243 8244 /* Take it off inuse list */ 8245 (xrip->_b)->_f = xrip->_f; 8246 (xrip->_f)->_b = xrip->_b; 8247 xrip->_f = NULL; 8248 xrip->_b = NULL; 8249 hba->sli.sli4.xria_count--; 8250 8251 /* Add it to end of free list */ 8252 xrip->_b = hba->sli.sli4.XRIfree_b; 8253 hba->sli.sli4.XRIfree_b->_f = xrip; 8254 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 8255 hba->sli.sli4.XRIfree_b = xrip; 8256 hba->sli.sli4.xrif_count++; 8257 8258 if (lock) { 8259 mutex_exit(&EMLXS_FCTAB_LOCK); 8260 } 8261 8262 return (0); 8263 8264 } /* emlxs_sli4_unreserve_xri() */ 8265 8266 8267 XRIobj_t * 8268 emlxs_sli4_register_xri(emlxs_port_t *port, emlxs_buf_t *sbp, uint16_t xri, 8269 uint32_t did) 8270 { 8271 emlxs_hba_t *hba = HBA; 8272 uint16_t iotag; 8273 XRIobj_t *xrip; 8274 emlxs_node_t *node; 8275 RPIobj_t *rpip; 8276 8277 mutex_enter(&EMLXS_FCTAB_LOCK); 8278 8279 xrip = sbp->xrip; 8280 if (!xrip) { 8281 xrip = emlxs_sli4_find_xri(port, xri); 8282 8283 if (!xrip) { 8284 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8285 "sli4_register_xri:%d XRI not found.", xri); 8286 8287 mutex_exit(&EMLXS_FCTAB_LOCK); 8288 return (NULL); 8289 } 8290 } 8291 8292 if ((xrip->state == XRI_STATE_FREE) || 8293 !(xrip->flag & EMLXS_XRI_RESERVED)) { 8294 8295 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8296 "sli4_register_xri:%d Invalid XRI. xrip=%p " 8297 "state=%x flag=%x", 8298 xrip->XRI, xrip, xrip->state, xrip->flag); 8299 8300 mutex_exit(&EMLXS_FCTAB_LOCK); 8301 return (NULL); 8302 } 8303 8304 iotag = xrip->iotag; 8305 8306 if ((!iotag) || 8307 ((hba->fc_table[iotag] != NULL) && 8308 (hba->fc_table[iotag] != STALE_PACKET))) { 8309 8310 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8311 "sli4_register_xri:%d Invalid fc_table entry. " 8312 "iotag=%d entry=%p", 8313 xrip->XRI, iotag, hba->fc_table[iotag]); 8314 8315 mutex_exit(&EMLXS_FCTAB_LOCK); 8316 return (NULL); 8317 } 8318 8319 hba->fc_table[iotag] = sbp; 8320 hba->io_count++; 8321 8322 sbp->iotag = iotag; 8323 sbp->xrip = xrip; 8324 8325 xrip->flag &= ~EMLXS_XRI_RESERVED; 8326 xrip->sbp = sbp; 8327 8328 /* If we did not have a registered RPI when we reserved */ 8329 /* this exchange, check again now. */ 8330 if (xrip->rpip && (xrip->rpip->RPI == FABRIC_RPI)) { 8331 node = emlxs_node_find_did(port, did, 1); 8332 rpip = EMLXS_NODE_TO_RPI(port, node); 8333 8334 if (rpip && (rpip->RPI != FABRIC_RPI)) { 8335 /* Move the XRI to the new RPI */ 8336 xrip->rpip->xri_count--; 8337 xrip->rpip = rpip; 8338 rpip->xri_count++; 8339 } 8340 } 8341 8342 mutex_exit(&EMLXS_FCTAB_LOCK); 8343 8344 return (xrip); 8345 8346 } /* emlxs_sli4_register_xri() */ 8347 8348 8349 /* Performs both reserve and register functions for XRI */ 8350 static XRIobj_t * 8351 emlxs_sli4_alloc_xri(emlxs_port_t *port, emlxs_buf_t *sbp, RPIobj_t *rpip, 8352 uint32_t type) 8353 { 8354 emlxs_hba_t *hba = HBA; 8355 XRIobj_t *xrip; 8356 uint16_t iotag; 8357 8358 mutex_enter(&EMLXS_FCTAB_LOCK); 8359 8360 xrip = hba->sli.sli4.XRIfree_f; 8361 8362 if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { 8363 mutex_exit(&EMLXS_FCTAB_LOCK); 8364 8365 return (NULL); 8366 } 8367 8368 /* Get the iotag by registering the packet */ 8369 iotag = xrip->iotag; 8370 8371 if ((!iotag) || 8372 ((hba->fc_table[iotag] != NULL) && 8373 (hba->fc_table[iotag] != STALE_PACKET))) { 8374 /* 8375 * No more command slots available, retry later 8376 */ 8377 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8378 "Adapter Busy. Unable to alloc iotag:(0x%x)(%p) type=%d", 8379 iotag, hba->fc_table[iotag], type); 8380 8381 mutex_exit(&EMLXS_FCTAB_LOCK); 8382 return (NULL); 8383 } 8384 8385 hba->fc_table[iotag] = sbp; 8386 hba->io_count++; 8387 8388 sbp->iotag = iotag; 8389 sbp->xrip = xrip; 8390 8391 xrip->state = XRI_STATE_ALLOCATED; 8392 xrip->type = type; 8393 xrip->flag = 0; 8394 xrip->sbp = sbp; 8395 8396 xrip->rpip = rpip; 8397 rpip->xri_count++; 8398 8399 /* Take it off free list */ 8400 (xrip->_b)->_f = xrip->_f; 8401 (xrip->_f)->_b = xrip->_b; 8402 xrip->_f = NULL; 8403 xrip->_b = NULL; 8404 hba->sli.sli4.xrif_count--; 8405 8406 /* Add it to end of inuse list */ 8407 xrip->_b = hba->sli.sli4.XRIinuse_b; 8408 hba->sli.sli4.XRIinuse_b->_f = xrip; 8409 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; 8410 hba->sli.sli4.XRIinuse_b = xrip; 8411 hba->sli.sli4.xria_count++; 8412 8413 mutex_exit(&EMLXS_FCTAB_LOCK); 8414 8415 return (xrip); 8416 8417 } /* emlxs_sli4_alloc_xri() */ 8418 8419 8420 /* EMLXS_FCTAB_LOCK must be held to enter */ 8421 extern XRIobj_t * 8422 emlxs_sli4_find_xri(emlxs_port_t *port, uint16_t xri) 8423 { 8424 emlxs_hba_t *hba = HBA; 8425 XRIobj_t *xrip; 8426 8427 xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; 8428 while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { 8429 if ((xrip->state >= XRI_STATE_ALLOCATED) && 8430 (xrip->XRI == xri)) { 8431 return (xrip); 8432 } 8433 xrip = xrip->_f; 8434 } 8435 8436 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8437 "Unable to find XRI x%x", xri); 8438 8439 return (NULL); 8440 8441 } /* emlxs_sli4_find_xri() */ 8442 8443 8444 8445 8446 extern void 8447 emlxs_sli4_free_xri(emlxs_port_t *port, emlxs_buf_t *sbp, XRIobj_t *xrip, 8448 uint8_t lock) 8449 { 8450 emlxs_hba_t *hba = HBA; 8451 8452 if (lock) { 8453 mutex_enter(&EMLXS_FCTAB_LOCK); 8454 } 8455 8456 if (xrip) { 8457 if (xrip->state == XRI_STATE_FREE) { 8458 if (lock) { 8459 mutex_exit(&EMLXS_FCTAB_LOCK); 8460 } 8461 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8462 "Free XRI:%x, Already freed. type=%d", 8463 xrip->XRI, xrip->type); 8464 return; 8465 } 8466 8467 if (xrip->type == EMLXS_XRI_UNSOL_CT_TYPE) { 8468 (void) emlxs_flush_ct_event(port, xrip->rx_id); 8469 } 8470 8471 if (xrip->iotag && 8472 (hba->fc_table[xrip->iotag] != NULL) && 8473 (hba->fc_table[xrip->iotag] != STALE_PACKET)) { 8474 hba->fc_table[xrip->iotag] = NULL; 8475 hba->io_count--; 8476 } 8477 8478 xrip->state = XRI_STATE_FREE; 8479 xrip->type = 0; 8480 xrip->flag = 0; 8481 8482 if (xrip->rpip) { 8483 xrip->rpip->xri_count--; 8484 xrip->rpip = NULL; 8485 } 8486 8487 if (xrip->reserved_rpip) { 8488 xrip->reserved_rpip->xri_count--; 8489 xrip->reserved_rpip = NULL; 8490 } 8491 8492 /* Take it off inuse list */ 8493 (xrip->_b)->_f = xrip->_f; 8494 (xrip->_f)->_b = xrip->_b; 8495 xrip->_f = NULL; 8496 xrip->_b = NULL; 8497 hba->sli.sli4.xria_count--; 8498 8499 /* Add it to end of free list */ 8500 xrip->_b = hba->sli.sli4.XRIfree_b; 8501 hba->sli.sli4.XRIfree_b->_f = xrip; 8502 xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; 8503 hba->sli.sli4.XRIfree_b = xrip; 8504 hba->sli.sli4.xrif_count++; 8505 } 8506 8507 if (sbp) { 8508 if (!(sbp->pkt_flags & PACKET_VALID) || 8509 (sbp->pkt_flags & 8510 (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) { 8511 if (lock) { 8512 mutex_exit(&EMLXS_FCTAB_LOCK); 8513 } 8514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8515 "Free XRI: sbp invalid. sbp=%p flags=%x xri=%d", 8516 sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0)); 8517 return; 8518 } 8519 8520 if (xrip && (xrip->iotag != sbp->iotag)) { 8521 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 8522 "sbp/iotag mismatch %p iotag:%d %d", sbp, 8523 sbp->iotag, xrip->iotag); 8524 } 8525 8526 if (sbp->iotag) { 8527 if (sbp == hba->fc_table[sbp->iotag]) { 8528 hba->fc_table[sbp->iotag] = NULL; 8529 hba->io_count--; 8530 8531 if (sbp->xrip) { 8532 /* Exchange is still reserved */ 8533 sbp->xrip->flag |= EMLXS_XRI_RESERVED; 8534 } 8535 } 8536 sbp->iotag = 0; 8537 } 8538 8539 if (xrip) { 8540 sbp->xrip = 0; 8541 } 8542 8543 if (lock) { 8544 mutex_exit(&EMLXS_FCTAB_LOCK); 8545 } 8546 8547 /* Clean up the sbp */ 8548 mutex_enter(&sbp->mtx); 8549 8550 if (sbp->pkt_flags & PACKET_IN_TXQ) { 8551 sbp->pkt_flags &= ~PACKET_IN_TXQ; 8552 hba->channel_tx_count--; 8553 } 8554 8555 if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 8556 sbp->pkt_flags &= ~PACKET_IN_CHIPQ; 8557 } 8558 8559 mutex_exit(&sbp->mtx); 8560 } else { 8561 if (lock) { 8562 mutex_exit(&EMLXS_FCTAB_LOCK); 8563 } 8564 } 8565 8566 } /* emlxs_sli4_free_xri() */ 8567 8568 8569 static int 8570 emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) 8571 { 8572 MAILBOX4 *mb = (MAILBOX4 *)mbq; 8573 emlxs_port_t *port = &PPORT; 8574 XRIobj_t *xrip; 8575 MATCHMAP *mp; 8576 mbox_req_hdr_t *hdr_req; 8577 uint32_t i; 8578 uint32_t cnt; 8579 uint32_t xri_cnt; 8580 uint32_t j; 8581 uint32_t size; 8582 IOCTL_FCOE_CFG_POST_SGL_PAGES *post_sgl; 8583 8584 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 8585 mbq->bp = NULL; 8586 mbq->mbox_cmpl = NULL; 8587 8588 if ((mp = emlxs_mem_buf_alloc(hba, EMLXS_MAX_NONEMBED_SIZE)) == 0) { 8589 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8590 "Unable to POST_SGL. Mailbox cmd=%x ", 8591 mb->mbxCommand); 8592 return (EIO); 8593 } 8594 mbq->nonembed = (void *)mp; 8595 8596 /* 8597 * Signifies a non embedded command 8598 */ 8599 mb->un.varSLIConfig.be.embedded = 0; 8600 mb->mbxCommand = MBX_SLI_CONFIG; 8601 mb->mbxOwner = OWN_HOST; 8602 8603 hdr_req = (mbox_req_hdr_t *)mp->virt; 8604 post_sgl = 8605 (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1); 8606 8607 xrip = hba->sli.sli4.XRIp; 8608 8609 /* For each extent */ 8610 for (j = 0; j < hba->sli.sli4.XRIExtCount; j++) { 8611 cnt = hba->sli.sli4.XRIExtSize; 8612 while (cnt) { 8613 if (xrip->XRI == 0) { 8614 cnt--; 8615 xrip++; 8616 continue; 8617 } 8618 8619 bzero((void *) hdr_req, mp->size); 8620 size = mp->size - IOCTL_HEADER_SZ; 8621 8622 mb->un.varSLIConfig.be.payload_length = 8623 mp->size; 8624 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 8625 IOCTL_SUBSYSTEM_FCOE; 8626 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = 8627 FCOE_OPCODE_CFG_POST_SGL_PAGES; 8628 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 8629 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = size; 8630 8631 hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; 8632 hdr_req->opcode = FCOE_OPCODE_CFG_POST_SGL_PAGES; 8633 hdr_req->timeout = 0; 8634 hdr_req->req_length = size; 8635 8636 post_sgl->params.request.xri_count = 0; 8637 post_sgl->params.request.xri_start = xrip->XRI; 8638 8639 xri_cnt = (size - 8640 sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) / 8641 sizeof (FCOE_SGL_PAGES); 8642 8643 for (i = 0; (i < xri_cnt) && cnt; i++) { 8644 post_sgl->params.request.xri_count++; 8645 post_sgl->params.request.pages[i].\ 8646 sgl_page0.addrLow = 8647 PADDR_LO(xrip->SGList->phys); 8648 post_sgl->params.request.pages[i].\ 8649 sgl_page0.addrHigh = 8650 PADDR_HI(xrip->SGList->phys); 8651 8652 cnt--; 8653 xrip++; 8654 } 8655 8656 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8657 MBX_SUCCESS) { 8658 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8659 "Unable to POST_SGL. Mailbox cmd=%x " 8660 "status=%x XRI cnt:%d start:%d", 8661 mb->mbxCommand, mb->mbxStatus, 8662 post_sgl->params.request.xri_count, 8663 post_sgl->params.request.xri_start); 8664 emlxs_mem_buf_free(hba, mp); 8665 mbq->nonembed = NULL; 8666 return (EIO); 8667 } 8668 } 8669 } 8670 8671 emlxs_mem_buf_free(hba, mp); 8672 mbq->nonembed = NULL; 8673 return (0); 8674 8675 } /* emlxs_sli4_post_sgl_pages() */ 8676 8677 8678 static int 8679 emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq) 8680 { 8681 MAILBOX4 *mb = (MAILBOX4 *)mbq; 8682 emlxs_port_t *port = &PPORT; 8683 uint32_t j; 8684 uint32_t k; 8685 uint64_t addr; 8686 IOCTL_FCOE_POST_HDR_TEMPLATES *post_hdr; 8687 uint16_t num_pages; 8688 8689 if (!(hba->sli.sli4.param.HDRR)) { 8690 return (0); 8691 } 8692 8693 /* Bytes per extent */ 8694 j = hba->sli.sli4.RPIExtSize * sizeof (RPIHdrTmplate_t); 8695 8696 /* Pages required per extent (page == 4096 bytes) */ 8697 num_pages = (j/4096) + ((j%4096)? 1:0); 8698 8699 addr = hba->sli.sli4.HeaderTmplate.phys; 8700 8701 /* For each extent */ 8702 for (j = 0; j < hba->sli.sli4.RPIExtCount; j++) { 8703 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 8704 mbq->bp = NULL; 8705 mbq->mbox_cmpl = NULL; 8706 8707 /* 8708 * Signifies an embedded command 8709 */ 8710 mb->un.varSLIConfig.be.embedded = 1; 8711 8712 mb->mbxCommand = MBX_SLI_CONFIG; 8713 mb->mbxOwner = OWN_HOST; 8714 mb->un.varSLIConfig.be.payload_length = 8715 sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES) + IOCTL_HEADER_SZ; 8716 mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = 8717 IOCTL_SUBSYSTEM_FCOE; 8718 mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = 8719 FCOE_OPCODE_POST_HDR_TEMPLATES; 8720 mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; 8721 mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 8722 sizeof (IOCTL_FCOE_POST_HDR_TEMPLATES); 8723 8724 post_hdr = 8725 (IOCTL_FCOE_POST_HDR_TEMPLATES *) 8726 &mb->un.varSLIConfig.payload; 8727 post_hdr->params.request.num_pages = num_pages; 8728 post_hdr->params.request.rpi_offset = hba->sli.sli4.RPIBase[j]; 8729 8730 for (k = 0; k < num_pages; k++) { 8731 post_hdr->params.request.pages[k].addrLow = 8732 PADDR_LO(addr); 8733 post_hdr->params.request.pages[k].addrHigh = 8734 PADDR_HI(addr); 8735 addr += 4096; 8736 } 8737 8738 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8739 MBX_SUCCESS) { 8740 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8741 "Unable to POST_HDR_TEMPLATES. Mailbox cmd=%x " 8742 "status=%x ", 8743 mb->mbxCommand, mb->mbxStatus); 8744 return (EIO); 8745 } 8746 emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0); 8747 } 8748 8749 return (0); 8750 8751 } /* emlxs_sli4_post_hdr_tmplates() */ 8752 8753 8754 static int 8755 emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq) 8756 { 8757 MAILBOX4 *mb = (MAILBOX4 *)mbq; 8758 emlxs_port_t *port = &PPORT; 8759 emlxs_config_t *cfg = &CFG; 8760 IOCTL_COMMON_EQ_CREATE *eq; 8761 IOCTL_COMMON_CQ_CREATE *cq; 8762 IOCTL_FCOE_WQ_CREATE *wq; 8763 IOCTL_FCOE_RQ_CREATE *rq; 8764 IOCTL_COMMON_MQ_CREATE *mq; 8765 IOCTL_COMMON_MQ_CREATE_EXT *mq_ext; 8766 uint16_t i, j; 8767 uint16_t num_cq, total_cq; 8768 uint16_t num_wq, total_wq; 8769 8770 /* 8771 * The first CQ is reserved for ASYNC events, 8772 * the second is reserved for unsol rcv, the rest 8773 * correspond to WQs. (WQ0 -> CQ2, WQ1 -> CQ3, ...) 8774 */ 8775 8776 total_cq = 0; 8777 total_wq = 0; 8778 8779 /* Create EQ's */ 8780 for (i = 0; i < hba->intr_count; i++) { 8781 emlxs_mb_eq_create(hba, mbq, i); 8782 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8783 MBX_SUCCESS) { 8784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 8785 "Unable to Create EQ %d: Mailbox cmd=%x status=%x ", 8786 i, mb->mbxCommand, mb->mbxStatus); 8787 return (EIO); 8788 } 8789 eq = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload; 8790 hba->sli.sli4.eq[i].qid = eq->params.response.EQId; 8791 hba->sli.sli4.eq[i].lastwq = total_wq; 8792 hba->sli.sli4.eq[i].msix_vector = i; 8793 8794 emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0); 8795 num_wq = cfg[CFG_NUM_WQ].current; 8796 num_cq = num_wq; 8797 if (i == 0) { 8798 /* One for RQ handling, one for mbox/event handling */ 8799 num_cq += EMLXS_CQ_OFFSET_WQ; 8800 } 8801 8802 /* Create CQ's */ 8803 for (j = 0; j < num_cq; j++) { 8804 /* Reuse mbq from previous mbox */ 8805 bzero(mbq, sizeof (MAILBOXQ)); 8806 8807 hba->sli.sli4.cq[total_cq].eqid = 8808 hba->sli.sli4.eq[i].qid; 8809 8810 emlxs_mb_cq_create(hba, mbq, total_cq); 8811 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8812 MBX_SUCCESS) { 8813 EMLXS_MSGF(EMLXS_CONTEXT, 8814 &emlxs_init_failed_msg, "Unable to Create " 8815 "CQ %d: hba=%p Mailbox cmd=%x status=%x ", 8816 total_cq, hba, mb->mbxCommand, 8817 mb->mbxStatus); 8818 return (EIO); 8819 } 8820 cq = (IOCTL_COMMON_CQ_CREATE *) 8821 &mb->un.varSLIConfig.payload; 8822 hba->sli.sli4.cq[total_cq].qid = 8823 cq->params.response.CQId; 8824 8825 switch (total_cq) { 8826 case EMLXS_CQ_MBOX: 8827 /* First CQ is for async event handling */ 8828 hba->sli.sli4.cq[total_cq].type = 8829 EMLXS_CQ_TYPE_GROUP1; 8830 break; 8831 8832 case EMLXS_CQ_RCV: 8833 /* Second CQ is for unsol receive handling */ 8834 hba->sli.sli4.cq[total_cq].type = 8835 EMLXS_CQ_TYPE_GROUP2; 8836 break; 8837 8838 default: 8839 /* Setup CQ to channel mapping */ 8840 hba->sli.sli4.cq[total_cq].type = 8841 EMLXS_CQ_TYPE_GROUP2; 8842 hba->sli.sli4.cq[total_cq].channelp = 8843 &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ]; 8844 break; 8845 } 8846 hba->sli.sli4.cq[total_cq].qe_valid = 1; 8847 emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb, 8848 18, 0); 8849 total_cq++; 8850 } 8851 8852 /* Create WQ's */ 8853 for (j = 0; j < num_wq; j++) { 8854 /* Reuse mbq from previous mbox */ 8855 bzero(mbq, sizeof (MAILBOXQ)); 8856 8857 hba->sli.sli4.wq[total_wq].cqid = 8858 hba->sli.sli4.cq[total_wq + EMLXS_CQ_OFFSET_WQ].qid; 8859 8860 emlxs_mb_wq_create(hba, mbq, total_wq); 8861 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8862 MBX_SUCCESS) { 8863 EMLXS_MSGF(EMLXS_CONTEXT, 8864 &emlxs_init_failed_msg, "Unable to Create " 8865 "WQ %d: Mailbox cmd=%x status=%x ", 8866 total_wq, mb->mbxCommand, mb->mbxStatus); 8867 return (EIO); 8868 } 8869 wq = (IOCTL_FCOE_WQ_CREATE *) 8870 &mb->un.varSLIConfig.payload; 8871 hba->sli.sli4.wq[total_wq].qid = 8872 wq->params.response.WQId; 8873 8874 hba->sli.sli4.wq[total_wq].cqid = 8875 hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid; 8876 emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb, 8877 18, 0); 8878 total_wq++; 8879 } 8880 hba->last_msiid = i; 8881 } 8882 8883 /* We assume 1 RQ pair will handle ALL incoming data */ 8884 /* Create RQs */ 8885 for (i = 0; i < EMLXS_MAX_RQS; i++) { 8886 /* Personalize the RQ */ 8887 switch (i) { 8888 case 0: 8889 hba->sli.sli4.rq[i].cqid = 8890 hba->sli.sli4.cq[EMLXS_CQ_RCV].qid; 8891 break; 8892 case 1: 8893 hba->sli.sli4.rq[i].cqid = 8894 hba->sli.sli4.cq[EMLXS_CQ_RCV].qid; 8895 break; 8896 default: 8897 hba->sli.sli4.rq[i].cqid = 0xffff; 8898 } 8899 8900 /* Reuse mbq from previous mbox */ 8901 bzero(mbq, sizeof (MAILBOXQ)); 8902 8903 emlxs_mb_rq_create(hba, mbq, i); 8904 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8905 MBX_SUCCESS) { 8906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 8907 "Unable to Create RQ %d: Mailbox cmd=%x status=%x ", 8908 i, mb->mbxCommand, mb->mbxStatus); 8909 return (EIO); 8910 } 8911 8912 rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload; 8913 hba->sli.sli4.rq[i].qid = rq->params.response.RQId; 8914 emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0); 8915 8916 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8917 "RQ CREATE: rq[%d].qid=%d cqid=%d", 8918 i, hba->sli.sli4.rq[i].qid, hba->sli.sli4.rq[i].cqid); 8919 8920 /* Initialize the host_index */ 8921 hba->sli.sli4.rq[i].host_index = 0; 8922 8923 /* If Data queue was just created, */ 8924 /* then post buffers using the header qid */ 8925 if ((i & 0x1)) { 8926 /* Ring the RQ doorbell to post buffers */ 8927 8928 emlxs_sli4_write_rqdb(hba, hba->sli.sli4.rq[i-1].qid, 8929 RQB_COUNT); 8930 8931 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8932 "RQ CREATE: Doorbell rang: qid=%d count=%d", 8933 hba->sli.sli4.rq[i-1].qid, RQB_COUNT); 8934 } 8935 } 8936 8937 /* Create MQ */ 8938 8939 /* Personalize the MQ */ 8940 hba->sli.sli4.mq.cqid = hba->sli.sli4.cq[EMLXS_CQ_MBOX].qid; 8941 8942 /* Reuse mbq from previous mbox */ 8943 bzero(mbq, sizeof (MAILBOXQ)); 8944 8945 emlxs_mb_mq_create_ext(hba, mbq); 8946 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8947 MBX_SUCCESS) { 8948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 8949 "Unable to Create MQ_EXT %d: Mailbox cmd=%x status=%x ", 8950 i, mb->mbxCommand, mb->mbxStatus); 8951 8952 /* Reuse mbq from previous mbox */ 8953 bzero(mbq, sizeof (MAILBOXQ)); 8954 8955 emlxs_mb_mq_create(hba, mbq); 8956 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 8957 MBX_SUCCESS) { 8958 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 8959 "Unable to Create MQ %d: Mailbox cmd=%x status=%x ", 8960 i, mb->mbxCommand, mb->mbxStatus); 8961 return (EIO); 8962 } 8963 8964 mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload; 8965 hba->sli.sli4.mq.qid = mq->params.response.MQId; 8966 return (0); 8967 } 8968 8969 mq_ext = (IOCTL_COMMON_MQ_CREATE_EXT *)&mb->un.varSLIConfig.payload; 8970 hba->sli.sli4.mq.qid = mq_ext->params.response.MQId; 8971 return (0); 8972 8973 } /* emlxs_sli4_create_queues() */ 8974 8975 8976 extern void 8977 emlxs_sli4_timer(emlxs_hba_t *hba) 8978 { 8979 /* Perform SLI4 level timer checks */ 8980 8981 emlxs_fcf_timer_notify(hba); 8982 8983 emlxs_sli4_timer_check_mbox(hba); 8984 8985 return; 8986 8987 } /* emlxs_sli4_timer() */ 8988 8989 8990 static void 8991 emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba) 8992 { 8993 emlxs_port_t *port = &PPORT; 8994 emlxs_config_t *cfg = &CFG; 8995 MAILBOX *mb = NULL; 8996 8997 if (!cfg[CFG_TIMEOUT_ENABLE].current) { 8998 return; 8999 } 9000 9001 mutex_enter(&EMLXS_PORT_LOCK); 9002 9003 /* Return if timer hasn't expired */ 9004 if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) { 9005 mutex_exit(&EMLXS_PORT_LOCK); 9006 return; 9007 } 9008 9009 /* The first to service the mbox queue will clear the timer */ 9010 hba->mbox_timer = 0; 9011 9012 if (hba->mbox_queue_flag) { 9013 if (hba->mbox_mbq) { 9014 mb = (MAILBOX *)hba->mbox_mbq; 9015 } 9016 } 9017 9018 if (mb) { 9019 switch (hba->mbox_queue_flag) { 9020 case MBX_NOWAIT: 9021 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 9022 "%s: Nowait.", 9023 emlxs_mb_cmd_xlate(mb->mbxCommand)); 9024 break; 9025 9026 case MBX_SLEEP: 9027 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 9028 "%s: mb=%p Sleep.", 9029 emlxs_mb_cmd_xlate(mb->mbxCommand), 9030 mb); 9031 break; 9032 9033 case MBX_POLL: 9034 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 9035 "%s: mb=%p Polled.", 9036 emlxs_mb_cmd_xlate(mb->mbxCommand), 9037 mb); 9038 break; 9039 9040 default: 9041 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 9042 "%s: mb=%p (%d).", 9043 emlxs_mb_cmd_xlate(mb->mbxCommand), 9044 mb, hba->mbox_queue_flag); 9045 break; 9046 } 9047 } else { 9048 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL); 9049 } 9050 9051 hba->flag |= FC_MBOX_TIMEOUT; 9052 EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR); 9053 9054 mutex_exit(&EMLXS_PORT_LOCK); 9055 9056 /* Perform mailbox cleanup */ 9057 /* This will wake any sleeping or polling threads */ 9058 emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 9059 9060 /* Trigger adapter shutdown */ 9061 emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0); 9062 9063 return; 9064 9065 } /* emlxs_sli4_timer_check_mbox() */ 9066 9067 static void 9068 emlxs_sli4_gpio_timer_start(emlxs_hba_t *hba) 9069 { 9070 mutex_enter(&hba->gpio_lock); 9071 9072 if (!hba->gpio_timer) { 9073 hba->gpio_timer = timeout(emlxs_sli4_gpio_timer, (void *)hba, 9074 drv_usectohz(100000)); 9075 } 9076 9077 mutex_exit(&hba->gpio_lock); 9078 9079 } /* emlxs_sli4_gpio_timer_start() */ 9080 9081 static void 9082 emlxs_sli4_gpio_timer_stop(emlxs_hba_t *hba) 9083 { 9084 mutex_enter(&hba->gpio_lock); 9085 9086 if (hba->gpio_timer) { 9087 (void) untimeout(hba->gpio_timer); 9088 hba->gpio_timer = 0; 9089 } 9090 9091 mutex_exit(&hba->gpio_lock); 9092 9093 delay(drv_usectohz(300000)); 9094 } /* emlxs_sli4_gpio_timer_stop() */ 9095 9096 static void 9097 emlxs_sli4_gpio_timer(void *arg) 9098 { 9099 emlxs_hba_t *hba = (emlxs_hba_t *)arg; 9100 9101 mutex_enter(&hba->gpio_lock); 9102 9103 if (hba->gpio_timer) { 9104 emlxs_sli4_check_gpio(hba); 9105 hba->gpio_timer = timeout(emlxs_sli4_gpio_timer, (void *)hba, 9106 drv_usectohz(100000)); 9107 } 9108 9109 mutex_exit(&hba->gpio_lock); 9110 } /* emlxs_sli4_gpio_timer() */ 9111 9112 static void 9113 emlxs_sli4_check_gpio(emlxs_hba_t *hba) 9114 { 9115 hba->gpio_desired = 0; 9116 9117 if (hba->flag & FC_GPIO_LINK_UP) { 9118 if (hba->io_active) 9119 hba->gpio_desired |= EMLXS_GPIO_ACT; 9120 9121 /* This is model specific to ATTO gen5 lancer cards */ 9122 9123 switch (hba->linkspeed) { 9124 case LA_4GHZ_LINK: 9125 hba->gpio_desired |= EMLXS_GPIO_LO; 9126 break; 9127 9128 case LA_8GHZ_LINK: 9129 hba->gpio_desired |= EMLXS_GPIO_HI; 9130 break; 9131 9132 case LA_16GHZ_LINK: 9133 hba->gpio_desired |= 9134 EMLXS_GPIO_LO | EMLXS_GPIO_HI; 9135 break; 9136 } 9137 } 9138 9139 if (hba->gpio_current != hba->gpio_desired) { 9140 emlxs_port_t *port = &PPORT; 9141 uint8_t pin; 9142 uint8_t pinval; 9143 MAILBOXQ *mbq; 9144 uint32_t rval; 9145 9146 if (!emlxs_sli4_fix_gpio(hba, &pin, &pinval)) 9147 return; 9148 9149 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == NULL) { 9150 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9151 "Unable to allocate GPIO mailbox."); 9152 9153 hba->gpio_bit = 0; 9154 return; 9155 } 9156 9157 emlxs_mb_gpio_write(hba, mbq, pin, pinval); 9158 mbq->mbox_cmpl = emlxs_sli4_fix_gpio_mbcmpl; 9159 9160 rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 9161 9162 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 9163 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9164 "Unable to start GPIO mailbox."); 9165 9166 hba->gpio_bit = 0; 9167 emlxs_mem_put(hba, MEM_MBOX, mbq); 9168 return; 9169 } 9170 } 9171 } /* emlxs_sli4_check_gpio */ 9172 9173 static uint32_t 9174 emlxs_sli4_fix_gpio(emlxs_hba_t *hba, uint8_t *pin, uint8_t *pinval) 9175 { 9176 uint8_t dif = hba->gpio_desired ^ hba->gpio_current; 9177 uint8_t bit; 9178 uint8_t i; 9179 9180 /* Get out if no pins to set a GPIO request is pending */ 9181 9182 if (dif == 0 || hba->gpio_bit) 9183 return (0); 9184 9185 /* Fix one pin at a time */ 9186 9187 bit = dif & -dif; 9188 hba->gpio_bit = bit; 9189 dif = hba->gpio_current ^ bit; 9190 9191 for (i = EMLXS_GPIO_PIN_LO; bit > 1; ++i) { 9192 dif >>= 1; 9193 bit >>= 1; 9194 } 9195 9196 /* Pins are active low so invert the bit value */ 9197 9198 *pin = hba->gpio_pin[i]; 9199 *pinval = ~dif & bit; 9200 9201 return (1); 9202 } /* emlxs_sli4_fix_gpio */ 9203 9204 static uint32_t 9205 emlxs_sli4_fix_gpio_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 9206 { 9207 MAILBOX *mb; 9208 uint8_t pin; 9209 uint8_t pinval; 9210 9211 mb = (MAILBOX *)mbq; 9212 9213 mutex_enter(&hba->gpio_lock); 9214 9215 if (mb->mbxStatus == 0) 9216 hba->gpio_current ^= hba->gpio_bit; 9217 9218 hba->gpio_bit = 0; 9219 9220 if (emlxs_sli4_fix_gpio(hba, &pin, &pinval)) { 9221 emlxs_port_t *port = &PPORT; 9222 MAILBOXQ *mbq; 9223 uint32_t rval; 9224 9225 /* 9226 * We're not using the mb_retry routine here because for some 9227 * reason it doesn't preserve the completion routine. Just let 9228 * this mbox cmd fail to start here and run when the mailbox 9229 * is no longer busy. 9230 */ 9231 9232 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == NULL) { 9233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9234 "Unable to allocate GPIO mailbox."); 9235 9236 hba->gpio_bit = 0; 9237 goto done; 9238 } 9239 9240 emlxs_mb_gpio_write(hba, mbq, pin, pinval); 9241 mbq->mbox_cmpl = emlxs_sli4_fix_gpio_mbcmpl; 9242 9243 rval = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 9244 9245 if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 9246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9247 "Unable to start GPIO mailbox."); 9248 9249 hba->gpio_bit = 0; 9250 emlxs_mem_put(hba, MEM_MBOX, mbq); 9251 goto done; 9252 } 9253 } 9254 9255 done: 9256 mutex_exit(&hba->gpio_lock); 9257 9258 return (0); 9259 } 9260 9261 extern void 9262 emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err) 9263 { 9264 void *msg; 9265 9266 if (!port || !str || !iptr || !cnt) { 9267 return; 9268 } 9269 9270 if (err) { 9271 msg = &emlxs_sli_err_msg; 9272 } else { 9273 msg = &emlxs_sli_detail_msg; 9274 } 9275 9276 if (cnt) { 9277 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9278 "%s00: %08x %08x %08x %08x %08x %08x", str, *iptr, 9279 *(iptr+1), *(iptr+2), *(iptr+3), *(iptr+4), *(iptr+5)); 9280 } 9281 if (cnt > 6) { 9282 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9283 "%s06: %08x %08x %08x %08x %08x %08x", str, *(iptr+6), 9284 *(iptr+7), *(iptr+8), *(iptr+9), *(iptr+10), *(iptr+11)); 9285 } 9286 if (cnt > 12) { 9287 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9288 "%s12: %08x %08x %08x %08x %08x %08x", str, *(iptr+12), 9289 *(iptr+13), *(iptr+14), *(iptr+15), *(iptr+16), *(iptr+17)); 9290 } 9291 if (cnt > 18) { 9292 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9293 "%s18: %08x %08x %08x %08x %08x %08x", str, *(iptr+18), 9294 *(iptr+19), *(iptr+20), *(iptr+21), *(iptr+22), *(iptr+23)); 9295 } 9296 if (cnt > 24) { 9297 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9298 "%s24: %08x %08x %08x %08x %08x %08x", str, *(iptr+24), 9299 *(iptr+25), *(iptr+26), *(iptr+27), *(iptr+28), *(iptr+29)); 9300 } 9301 if (cnt > 30) { 9302 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9303 "%s30: %08x %08x %08x %08x %08x %08x", str, *(iptr+30), 9304 *(iptr+31), *(iptr+32), *(iptr+33), *(iptr+34), *(iptr+35)); 9305 } 9306 if (cnt > 36) { 9307 EMLXS_MSGF(EMLXS_CONTEXT, msg, 9308 "%s36: %08x %08x %08x %08x %08x %08x", str, *(iptr+36), 9309 *(iptr+37), *(iptr+38), *(iptr+39), *(iptr+40), *(iptr+41)); 9310 } 9311 9312 } /* emlxs_data_dump() */ 9313 9314 9315 extern void 9316 emlxs_ue_dump(emlxs_hba_t *hba, char *str) 9317 { 9318 emlxs_port_t *port = &PPORT; 9319 uint32_t status; 9320 uint32_t ue_h; 9321 uint32_t ue_l; 9322 uint32_t on1; 9323 uint32_t on2; 9324 9325 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 9326 case SLI_INTF_IF_TYPE_0: 9327 ue_l = ddi_get32(hba->pci_acc_handle, 9328 hba->sli.sli4.ERR1_reg_addr); 9329 ue_h = ddi_get32(hba->pci_acc_handle, 9330 hba->sli.sli4.ERR2_reg_addr); 9331 9332 on1 = ddi_get32(hba->pci_acc_handle, 9333 (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE1)); 9334 on2 = ddi_get32(hba->pci_acc_handle, 9335 (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_ONLINE2)); 9336 9337 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9338 "%s: ueLow:%08x ueHigh:%08x on1:%08x on2:%08x", str, 9339 ue_l, ue_h, on1, on2); 9340 break; 9341 9342 case SLI_INTF_IF_TYPE_2: 9343 case SLI_INTF_IF_TYPE_6: 9344 status = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9345 hba->sli.sli4.STATUS_reg_addr); 9346 9347 ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9348 hba->sli.sli4.ERR1_reg_addr); 9349 ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9350 hba->sli.sli4.ERR2_reg_addr); 9351 9352 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9353 "%s: status:%08x err1:%08x err2:%08x", str, 9354 status, ue_l, ue_h); 9355 9356 break; 9357 } 9358 9359 #ifdef FMA_SUPPORT 9360 /* Access handle validation */ 9361 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 9362 #endif /* FMA_SUPPORT */ 9363 9364 } /* emlxs_ue_dump() */ 9365 9366 9367 static void 9368 emlxs_sli4_poll_erratt(emlxs_hba_t *hba) 9369 { 9370 emlxs_port_t *port = &PPORT; 9371 uint32_t status; 9372 uint32_t ue_h; 9373 uint32_t ue_l; 9374 uint32_t error = 0; 9375 9376 if (hba->flag & FC_HARDWARE_ERROR) { 9377 return; 9378 } 9379 9380 switch (hba->sli_intf & SLI_INTF_IF_TYPE_MASK) { 9381 case SLI_INTF_IF_TYPE_0: 9382 ue_l = ddi_get32(hba->pci_acc_handle, 9383 hba->sli.sli4.ERR1_reg_addr); 9384 ue_h = ddi_get32(hba->pci_acc_handle, 9385 hba->sli.sli4.ERR2_reg_addr); 9386 9387 if ((~hba->sli.sli4.ue_mask_lo & ue_l) || 9388 (~hba->sli.sli4.ue_mask_hi & ue_h) || 9389 (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) { 9390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 9391 "Host Error: ueLow:%08x ueHigh:%08x maskLow:%08x " 9392 "maskHigh:%08x flag:%08x", 9393 ue_l, ue_h, hba->sli.sli4.ue_mask_lo, 9394 hba->sli.sli4.ue_mask_hi, hba->sli.sli4.flag); 9395 9396 error = 2; 9397 } 9398 break; 9399 9400 case SLI_INTF_IF_TYPE_2: 9401 case SLI_INTF_IF_TYPE_6: 9402 status = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9403 hba->sli.sli4.STATUS_reg_addr); 9404 9405 if ((status & SLI_STATUS_ERROR) || 9406 (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) { 9407 ue_l = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9408 hba->sli.sli4.ERR1_reg_addr); 9409 ue_h = ddi_get32(hba->sli.sli4.bar0_acc_handle, 9410 hba->sli.sli4.ERR2_reg_addr); 9411 9412 error = (status & SLI_STATUS_RESET_NEEDED)? 1:2; 9413 9414 if (error == 1) { 9415 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, 9416 "Host Error: status:%08x err1:%08x " 9417 "err2:%08x flag:%08x reset", 9418 status, ue_l, ue_h, hba->sli.sli4.flag); 9419 } else { 9420 EMLXS_MSGF(EMLXS_CONTEXT, 9421 &emlxs_hardware_error_msg, 9422 "Host Error: status:%08x err1:%08x " 9423 "err2:%08x flag:%08x shutdown", 9424 status, ue_l, ue_h, hba->sli.sli4.flag); 9425 } 9426 } 9427 break; 9428 } 9429 9430 if (error == 2) { 9431 EMLXS_STATE_CHANGE(hba, FC_ERROR); 9432 9433 emlxs_sli4_hba_flush_chipq(hba); 9434 9435 emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0); 9436 9437 } else if (error == 1) { 9438 EMLXS_STATE_CHANGE(hba, FC_ERROR); 9439 9440 emlxs_sli4_hba_flush_chipq(hba); 9441 9442 emlxs_thread_spawn(hba, emlxs_restart_thread, 0, 0); 9443 } 9444 9445 #ifdef FMA_SUPPORT 9446 /* Access handle validation */ 9447 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 9448 #endif /* FMA_SUPPORT */ 9449 9450 } /* emlxs_sli4_poll_erratt() */ 9451 9452 9453 static uint32_t 9454 emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, 9455 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) 9456 { 9457 emlxs_hba_t *hba = HBA; 9458 NODELIST *node; 9459 RPIobj_t *rpip; 9460 uint32_t rval; 9461 9462 /* Check for invalid node ids to register */ 9463 if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 9464 return (1); 9465 } 9466 9467 if (did & 0xff000000) { 9468 return (1); 9469 } 9470 9471 /* We don't register our own did */ 9472 if ((did == port->did) && (!(hba->flag & FC_LOOPBACK_MODE))) { 9473 return (1); 9474 } 9475 9476 if (did != FABRIC_DID) { 9477 if ((rval = emlxs_mb_check_sparm(hba, param))) { 9478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 9479 "Invalid service parameters. did=%06x rval=%d", did, 9480 rval); 9481 9482 return (1); 9483 } 9484 } 9485 9486 /* Check if the node limit has been reached */ 9487 if (port->node_count >= hba->max_nodes) { 9488 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 9489 "Limit reached. did=%06x count=%d", did, 9490 port->node_count); 9491 9492 return (1); 9493 } 9494 9495 node = emlxs_node_find_did(port, did, 1); 9496 rpip = EMLXS_NODE_TO_RPI(port, node); 9497 9498 rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp, 9499 (void *)ubp, (void *)iocbq); 9500 9501 return (rval); 9502 9503 } /* emlxs_sli4_reg_did() */ 9504 9505 9506 static uint32_t 9507 emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node, 9508 emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) 9509 { 9510 RPIobj_t *rpip; 9511 uint32_t rval; 9512 9513 if (!node) { 9514 /* Unreg all nodes */ 9515 (void) emlxs_sli4_unreg_all_nodes(port); 9516 return (1); 9517 } 9518 9519 /* Check for base node */ 9520 if (node == &port->node_base) { 9521 /* Just flush base node */ 9522 (void) emlxs_tx_node_flush(port, &port->node_base, 9523 0, 0, 0); 9524 9525 (void) emlxs_chipq_node_flush(port, 0, 9526 &port->node_base, 0); 9527 9528 port->did = 0; 9529 9530 /* Return now */ 9531 return (1); 9532 } 9533 9534 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9535 "unreg_node:%p did=%x rpi=%d", 9536 node, node->nlp_DID, node->nlp_Rpi); 9537 9538 rpip = EMLXS_NODE_TO_RPI(port, node); 9539 9540 if (!rpip) { 9541 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9542 "unreg_node:%p did=%x rpi=%d. RPI not found.", 9543 node, node->nlp_DID, node->nlp_Rpi); 9544 9545 emlxs_node_rm(port, node); 9546 return (1); 9547 } 9548 9549 rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp, 9550 (void *)iocbq); 9551 9552 return (rval); 9553 9554 } /* emlxs_sli4_unreg_node() */ 9555 9556 9557 extern uint32_t 9558 emlxs_sli4_unreg_all_nodes(emlxs_port_t *port) 9559 { 9560 NODELIST *nlp; 9561 int i; 9562 uint32_t found; 9563 9564 /* Set the node tags */ 9565 /* We will process all nodes with this tag */ 9566 rw_enter(&port->node_rwlock, RW_READER); 9567 found = 0; 9568 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9569 nlp = port->node_table[i]; 9570 while (nlp != NULL) { 9571 found = 1; 9572 nlp->nlp_tag = 1; 9573 nlp = nlp->nlp_list_next; 9574 } 9575 } 9576 rw_exit(&port->node_rwlock); 9577 9578 if (!found) { 9579 return (0); 9580 } 9581 9582 for (;;) { 9583 rw_enter(&port->node_rwlock, RW_READER); 9584 found = 0; 9585 for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 9586 nlp = port->node_table[i]; 9587 while (nlp != NULL) { 9588 if (!nlp->nlp_tag) { 9589 nlp = nlp->nlp_list_next; 9590 continue; 9591 } 9592 nlp->nlp_tag = 0; 9593 found = 1; 9594 break; 9595 } 9596 9597 if (found) { 9598 break; 9599 } 9600 } 9601 rw_exit(&port->node_rwlock); 9602 9603 if (!found) { 9604 break; 9605 } 9606 9607 (void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0); 9608 } 9609 9610 return (0); 9611 9612 } /* emlxs_sli4_unreg_all_nodes() */ 9613 9614 9615 static void 9616 emlxs_sli4_handle_fcoe_link_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe) 9617 { 9618 emlxs_port_t *port = &PPORT; 9619 9620 /* Handle link down */ 9621 if ((cqe->un.link.link_status == ASYNC_EVENT_LOGICAL_LINK_DOWN) || 9622 (cqe->un.link.link_status == ASYNC_EVENT_PHYS_LINK_DOWN)) { 9623 (void) emlxs_fcf_linkdown_notify(port); 9624 9625 mutex_enter(&EMLXS_PORT_LOCK); 9626 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK; 9627 mutex_exit(&EMLXS_PORT_LOCK); 9628 return; 9629 } 9630 9631 /* Link is up */ 9632 9633 /* Set linkspeed */ 9634 switch (cqe->un.link.port_speed) { 9635 case PHY_1GHZ_LINK: 9636 hba->linkspeed = LA_1GHZ_LINK; 9637 break; 9638 case PHY_10GHZ_LINK: 9639 hba->linkspeed = LA_10GHZ_LINK; 9640 break; 9641 default: 9642 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9643 "sli4_handle_fcoe_link_event: Unknown link speed=%x.", 9644 cqe->un.link.port_speed); 9645 hba->linkspeed = 0; 9646 break; 9647 } 9648 9649 /* Set qos_linkspeed */ 9650 hba->qos_linkspeed = cqe->un.link.qos_link_speed; 9651 9652 /* Set topology */ 9653 hba->topology = TOPOLOGY_PT_PT; 9654 9655 mutex_enter(&EMLXS_PORT_LOCK); 9656 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK; 9657 mutex_exit(&EMLXS_PORT_LOCK); 9658 9659 (void) emlxs_fcf_linkup_notify(port); 9660 9661 return; 9662 9663 } /* emlxs_sli4_handle_fcoe_link_event() */ 9664 9665 9666 static void 9667 emlxs_sli4_handle_fc_link_att(emlxs_hba_t *hba, CQE_ASYNC_t *cqe) 9668 { 9669 emlxs_port_t *port = &PPORT; 9670 9671 /* Handle link down */ 9672 if (cqe->un.fc.att_type == ATT_TYPE_LINK_DOWN) { 9673 (void) emlxs_fcf_linkdown_notify(port); 9674 9675 mutex_enter(&EMLXS_PORT_LOCK); 9676 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK; 9677 mutex_exit(&EMLXS_PORT_LOCK); 9678 return; 9679 } 9680 9681 /* Link is up */ 9682 9683 /* Set linkspeed */ 9684 switch (cqe->un.fc.port_speed) { 9685 case 1: 9686 hba->linkspeed = LA_1GHZ_LINK; 9687 break; 9688 case 2: 9689 hba->linkspeed = LA_2GHZ_LINK; 9690 break; 9691 case 4: 9692 hba->linkspeed = LA_4GHZ_LINK; 9693 break; 9694 case 8: 9695 hba->linkspeed = LA_8GHZ_LINK; 9696 break; 9697 case 10: 9698 hba->linkspeed = LA_10GHZ_LINK; 9699 break; 9700 case 16: 9701 hba->linkspeed = LA_16GHZ_LINK; 9702 break; 9703 case 32: 9704 hba->linkspeed = LA_32GHZ_LINK; 9705 break; 9706 default: 9707 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 9708 "sli4_handle_fc_link_att: Unknown link speed=%x.", 9709 cqe->un.fc.port_speed); 9710 hba->linkspeed = 0; 9711 break; 9712 } 9713 9714 /* Set qos_linkspeed */ 9715 hba->qos_linkspeed = cqe->un.fc.link_speed; 9716 9717 /* Set topology */ 9718 hba->topology = cqe->un.fc.topology; 9719 9720 mutex_enter(&EMLXS_PORT_LOCK); 9721 hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK; 9722 mutex_exit(&EMLXS_PORT_LOCK); 9723 9724 (void) emlxs_fcf_linkup_notify(port); 9725 9726 return; 9727 9728 } /* emlxs_sli4_handle_fc_link_att() */ 9729 9730 9731 static int 9732 emlxs_sli4_init_extents(emlxs_hba_t *hba, MAILBOXQ *mbq) 9733 { 9734 emlxs_port_t *port = &PPORT; 9735 MAILBOX4 *mb4; 9736 IOCTL_COMMON_EXTENTS *ep; 9737 uint32_t i; 9738 uint32_t ExtentCnt; 9739 9740 if (!(hba->sli.sli4.param.EXT)) { 9741 return (0); 9742 } 9743 9744 mb4 = (MAILBOX4 *) mbq; 9745 9746 /* Discover XRI Extents */ 9747 bzero(mbq, sizeof (MAILBOXQ)); 9748 emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_XRI); 9749 9750 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9752 "Unable to discover XRI extents. Mailbox cmd=%x status=%x", 9753 mb4->mbxCommand, mb4->mbxStatus); 9754 9755 return (EIO); 9756 } 9757 9758 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9759 hba->sli.sli4.XRIExtSize = ep->params.response.ExtentSize; 9760 ExtentCnt = ep->params.response.ExtentCnt; 9761 9762 /* Allocate XRI Extents */ 9763 bzero(mbq, sizeof (MAILBOXQ)); 9764 emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_XRI, ExtentCnt); 9765 9766 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9768 "Unable to allocate XRI extents. Mailbox cmd=%x status=%x", 9769 mb4->mbxCommand, mb4->mbxStatus); 9770 9771 return (EIO); 9772 } 9773 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9774 9775 bcopy((uint8_t *)ep->params.response.RscId, 9776 (uint8_t *)hba->sli.sli4.XRIBase, 9777 (ep->params.response.ExtentCnt * sizeof (uint16_t))); 9778 9779 hba->sli.sli4.XRIExtCount = ep->params.response.ExtentCnt; 9780 hba->sli.sli4.XRICount = hba->sli.sli4.XRIExtCount * 9781 hba->sli.sli4.XRIExtSize; 9782 9783 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9784 "XRI Ext: size=%d cnt=%d/%d", 9785 hba->sli.sli4.XRIExtSize, 9786 hba->sli.sli4.XRIExtCount, ExtentCnt); 9787 9788 for (i = 0; i < ep->params.response.ExtentCnt; i += 4) { 9789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9790 "XRI Ext%d: %d, %d, %d, %d", i, 9791 hba->sli.sli4.XRIBase[i], 9792 hba->sli.sli4.XRIBase[i+1], 9793 hba->sli.sli4.XRIBase[i+2], 9794 hba->sli.sli4.XRIBase[i+3]); 9795 } 9796 9797 9798 /* Discover RPI Extents */ 9799 bzero(mbq, sizeof (MAILBOXQ)); 9800 emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_RPI); 9801 9802 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9803 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9804 "Unable to discover RPI extents. Mailbox cmd=%x status=%x", 9805 mb4->mbxCommand, mb4->mbxStatus); 9806 9807 return (EIO); 9808 } 9809 9810 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9811 hba->sli.sli4.RPIExtSize = ep->params.response.ExtentSize; 9812 ExtentCnt = ep->params.response.ExtentCnt; 9813 9814 /* Allocate RPI Extents */ 9815 bzero(mbq, sizeof (MAILBOXQ)); 9816 emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_RPI, ExtentCnt); 9817 9818 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9819 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9820 "Unable to allocate RPI extents. Mailbox cmd=%x status=%x", 9821 mb4->mbxCommand, mb4->mbxStatus); 9822 9823 return (EIO); 9824 } 9825 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9826 9827 bcopy((uint8_t *)ep->params.response.RscId, 9828 (uint8_t *)hba->sli.sli4.RPIBase, 9829 (ep->params.response.ExtentCnt * sizeof (uint16_t))); 9830 9831 hba->sli.sli4.RPIExtCount = ep->params.response.ExtentCnt; 9832 hba->sli.sli4.RPICount = hba->sli.sli4.RPIExtCount * 9833 hba->sli.sli4.RPIExtSize; 9834 9835 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9836 "RPI Ext: size=%d cnt=%d/%d", 9837 hba->sli.sli4.RPIExtSize, 9838 hba->sli.sli4.RPIExtCount, ExtentCnt); 9839 9840 for (i = 0; i < ep->params.response.ExtentCnt; i += 4) { 9841 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9842 "RPI Ext%d: %d, %d, %d, %d", i, 9843 hba->sli.sli4.RPIBase[i], 9844 hba->sli.sli4.RPIBase[i+1], 9845 hba->sli.sli4.RPIBase[i+2], 9846 hba->sli.sli4.RPIBase[i+3]); 9847 } 9848 9849 9850 /* Discover VPI Extents */ 9851 bzero(mbq, sizeof (MAILBOXQ)); 9852 emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VPI); 9853 9854 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9855 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9856 "Unable to discover VPI extents. Mailbox cmd=%x status=%x", 9857 mb4->mbxCommand, mb4->mbxStatus); 9858 9859 return (EIO); 9860 } 9861 9862 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9863 hba->sli.sli4.VPIExtSize = ep->params.response.ExtentSize; 9864 ExtentCnt = ep->params.response.ExtentCnt; 9865 9866 /* Allocate VPI Extents */ 9867 bzero(mbq, sizeof (MAILBOXQ)); 9868 emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VPI, ExtentCnt); 9869 9870 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9871 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9872 "Unable to allocate VPI extents. Mailbox cmd=%x status=%x", 9873 mb4->mbxCommand, mb4->mbxStatus); 9874 9875 return (EIO); 9876 } 9877 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9878 9879 bcopy((uint8_t *)ep->params.response.RscId, 9880 (uint8_t *)hba->sli.sli4.VPIBase, 9881 (ep->params.response.ExtentCnt * sizeof (uint16_t))); 9882 9883 hba->sli.sli4.VPIExtCount = ep->params.response.ExtentCnt; 9884 hba->sli.sli4.VPICount = hba->sli.sli4.VPIExtCount * 9885 hba->sli.sli4.VPIExtSize; 9886 9887 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9888 "VPI Ext: size=%d cnt=%d/%d", 9889 hba->sli.sli4.VPIExtSize, 9890 hba->sli.sli4.VPIExtCount, ExtentCnt); 9891 9892 for (i = 0; i < ep->params.response.ExtentCnt; i += 4) { 9893 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9894 "VPI Ext%d: %d, %d, %d, %d", i, 9895 hba->sli.sli4.VPIBase[i], 9896 hba->sli.sli4.VPIBase[i+1], 9897 hba->sli.sli4.VPIBase[i+2], 9898 hba->sli.sli4.VPIBase[i+3]); 9899 } 9900 9901 /* Discover VFI Extents */ 9902 bzero(mbq, sizeof (MAILBOXQ)); 9903 emlxs_mb_get_extents_info(hba, mbq, RSC_TYPE_FCOE_VFI); 9904 9905 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9907 "Unable to discover VFI extents. Mailbox cmd=%x status=%x", 9908 mb4->mbxCommand, mb4->mbxStatus); 9909 9910 return (EIO); 9911 } 9912 9913 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9914 hba->sli.sli4.VFIExtSize = ep->params.response.ExtentSize; 9915 ExtentCnt = ep->params.response.ExtentCnt; 9916 9917 /* Allocate VFI Extents */ 9918 bzero(mbq, sizeof (MAILBOXQ)); 9919 emlxs_mb_alloc_extents(hba, mbq, RSC_TYPE_FCOE_VFI, ExtentCnt); 9920 9921 if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 9922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 9923 "Unable to allocate VFI extents. Mailbox cmd=%x status=%x", 9924 mb4->mbxCommand, mb4->mbxStatus); 9925 9926 return (EIO); 9927 } 9928 ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload; 9929 9930 bcopy((uint8_t *)ep->params.response.RscId, 9931 (uint8_t *)hba->sli.sli4.VFIBase, 9932 (ep->params.response.ExtentCnt * sizeof (uint16_t))); 9933 9934 hba->sli.sli4.VFIExtCount = ep->params.response.ExtentCnt; 9935 hba->sli.sli4.VFICount = hba->sli.sli4.VFIExtCount * 9936 hba->sli.sli4.VFIExtSize; 9937 9938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9939 "VFI Ext: size=%d cnt=%d/%d", 9940 hba->sli.sli4.VFIExtSize, 9941 hba->sli.sli4.VFIExtCount, ExtentCnt); 9942 9943 for (i = 0; i < ep->params.response.ExtentCnt; i += 4) { 9944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 9945 "VFI Ext%d: %d, %d, %d, %d", i, 9946 hba->sli.sli4.VFIBase[i], 9947 hba->sli.sli4.VFIBase[i+1], 9948 hba->sli.sli4.VFIBase[i+2], 9949 hba->sli.sli4.VFIBase[i+3]); 9950 } 9951 9952 return (0); 9953 9954 } /* emlxs_sli4_init_extents() */ 9955 9956 9957 extern uint32_t 9958 emlxs_sli4_index_to_rpi(emlxs_hba_t *hba, uint32_t index) 9959 { 9960 uint32_t i; 9961 uint32_t j; 9962 uint32_t rpi; 9963 9964 i = index / hba->sli.sli4.RPIExtSize; 9965 j = index % hba->sli.sli4.RPIExtSize; 9966 rpi = hba->sli.sli4.RPIBase[i] + j; 9967 9968 return (rpi); 9969 9970 } /* emlxs_sli4_index_to_rpi */ 9971 9972 9973 extern uint32_t 9974 emlxs_sli4_rpi_to_index(emlxs_hba_t *hba, uint32_t rpi) 9975 { 9976 uint32_t i; 9977 uint32_t lo; 9978 uint32_t hi; 9979 uint32_t index = hba->sli.sli4.RPICount; 9980 9981 for (i = 0; i < hba->sli.sli4.RPIExtCount; i++) { 9982 lo = hba->sli.sli4.RPIBase[i]; 9983 hi = lo + hba->sli.sli4.RPIExtSize; 9984 9985 if ((rpi < hi) && (rpi >= lo)) { 9986 index = (i * hba->sli.sli4.RPIExtSize) + (rpi - lo); 9987 break; 9988 } 9989 } 9990 9991 return (index); 9992 9993 } /* emlxs_sli4_rpi_to_index */ 9994 9995 9996 extern uint32_t 9997 emlxs_sli4_index_to_xri(emlxs_hba_t *hba, uint32_t index) 9998 { 9999 uint32_t i; 10000 uint32_t j; 10001 uint32_t xri; 10002 10003 i = index / hba->sli.sli4.XRIExtSize; 10004 j = index % hba->sli.sli4.XRIExtSize; 10005 xri = hba->sli.sli4.XRIBase[i] + j; 10006 10007 return (xri); 10008 10009 } /* emlxs_sli4_index_to_xri */ 10010 10011 10012 10013 10014 extern uint32_t 10015 emlxs_sli4_index_to_vpi(emlxs_hba_t *hba, uint32_t index) 10016 { 10017 uint32_t i; 10018 uint32_t j; 10019 uint32_t vpi; 10020 10021 i = index / hba->sli.sli4.VPIExtSize; 10022 j = index % hba->sli.sli4.VPIExtSize; 10023 vpi = hba->sli.sli4.VPIBase[i] + j; 10024 10025 return (vpi); 10026 10027 } /* emlxs_sli4_index_to_vpi */ 10028 10029 10030 extern uint32_t 10031 emlxs_sli4_vpi_to_index(emlxs_hba_t *hba, uint32_t vpi) 10032 { 10033 uint32_t i; 10034 uint32_t lo; 10035 uint32_t hi; 10036 uint32_t index = hba->sli.sli4.VPICount; 10037 10038 for (i = 0; i < hba->sli.sli4.VPIExtCount; i++) { 10039 lo = hba->sli.sli4.VPIBase[i]; 10040 hi = lo + hba->sli.sli4.VPIExtSize; 10041 10042 if ((vpi < hi) && (vpi >= lo)) { 10043 index = (i * hba->sli.sli4.VPIExtSize) + (vpi - lo); 10044 break; 10045 } 10046 } 10047 10048 return (index); 10049 10050 } /* emlxs_sli4_vpi_to_index */ 10051 10052 10053 10054 10055 extern uint32_t 10056 emlxs_sli4_index_to_vfi(emlxs_hba_t *hba, uint32_t index) 10057 { 10058 uint32_t i; 10059 uint32_t j; 10060 uint32_t vfi; 10061 10062 i = index / hba->sli.sli4.VFIExtSize; 10063 j = index % hba->sli.sli4.VFIExtSize; 10064 vfi = hba->sli.sli4.VFIBase[i] + j; 10065 10066 return (vfi); 10067 10068 } /* emlxs_sli4_index_to_vfi */ 10069 10070 10071 static uint16_t 10072 emlxs_sli4_rqid_to_index(emlxs_hba_t *hba, uint16_t rqid) 10073 { 10074 uint16_t i; 10075 10076 if (rqid < 0xffff) { 10077 for (i = 0; i < EMLXS_MAX_RQS; i++) { 10078 if (hba->sli.sli4.rq[i].qid == rqid) { 10079 return (i); 10080 } 10081 } 10082 } 10083 10084 return (0xffff); 10085 10086 } /* emlxs_sli4_rqid_to_index */ 10087 10088 10089 static uint16_t 10090 emlxs_sli4_wqid_to_index(emlxs_hba_t *hba, uint16_t wqid) 10091 { 10092 uint16_t i; 10093 10094 if (wqid < 0xffff) { 10095 for (i = 0; i < EMLXS_MAX_WQS; i++) { 10096 if (hba->sli.sli4.wq[i].qid == wqid) { 10097 return (i); 10098 } 10099 } 10100 } 10101 10102 return (0xffff); 10103 10104 } /* emlxs_sli4_wqid_to_index */ 10105 10106 10107 static uint16_t 10108 emlxs_sli4_cqid_to_index(emlxs_hba_t *hba, uint16_t cqid) 10109 { 10110 uint16_t i; 10111 10112 if (cqid < 0xffff) { 10113 for (i = 0; i < EMLXS_MAX_CQS; i++) { 10114 if (hba->sli.sli4.cq[i].qid == cqid) { 10115 return (i); 10116 } 10117 } 10118 } 10119 10120 return (0xffff); 10121 10122 } /* emlxs_sli4_cqid_to_index */ 10123