diff options
| author | Garrett D'Amore <garrett@damore.org> | 2012-01-25 22:01:17 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2012-01-25 22:01:17 -0800 |
| commit | a9800beb32c1006bb21c8da39e0180ea440b7bad (patch) | |
| tree | 2cf60f168e6ca0ee5db11e16fef4505c1fee4631 /usr/src/uts/common/io/fibre-channel | |
| parent | 528b7d8ba791f2da280ff1ddd45c61eb47a2744e (diff) | |
| download | illumos-gate-a9800beb32c1006bb21c8da39e0180ea440b7bad.tar.gz | |
1890 Updated emlxs driver from Emulex
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Reviewed by: Jean-Yves.Chevallier <Jean-Yves.Chevallier@Emulex.Com>
Approved by: Gordon Ross <gwr@nexenta.com>
Diffstat (limited to 'usr/src/uts/common/io/fibre-channel')
22 files changed, 16802 insertions, 4696 deletions
diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c index 0e59da5fe3..c984682b60 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2010 Emulex. All rights reserved. + * Copyright 2011 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -87,8 +87,6 @@ emlxs_timer(void *arg) mutex_enter(&EMLXS_TIMER_LOCK); - EMLXS_SLI_POLL_ERRATT(hba); - /* Only one timer thread is allowed */ if (hba->timer_flags & EMLXS_TIMER_BUSY) { mutex_exit(&EMLXS_TIMER_LOCK); @@ -109,6 +107,8 @@ emlxs_timer(void *arg) mutex_exit(&EMLXS_TIMER_LOCK); + EMLXS_SLI_POLL_ERRATT(hba); + /* Perform standard checks */ emlxs_timer_checks(hba); @@ -437,8 +437,7 @@ emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag) sbp = iocbq->sbp; if (sbp && (sbp != STALE_PACKET)) { if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } else { (void) emlxs_unregister_pkt( (CHANNEL *)iocbq->channel, @@ -501,8 +500,25 @@ emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag) mutex_enter(&EMLXS_FCTAB_LOCK); for (iotag = 1; iotag < hba->max_iotag; iotag++) { sbp = hba->fc_table[iotag]; - if (sbp && (sbp != STALE_PACKET) && - (sbp->pkt_flags & PACKET_IN_CHIPQ) && + + if (!sbp || (sbp == STALE_PACKET)) { + continue; + } + + /* Check if IO is valid */ + if (!(sbp->pkt_flags & PACKET_VALID) || + (sbp->pkt_flags & (PACKET_ULP_OWNED| + PACKET_COMPLETED|PACKET_IN_COMPLETION))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, + "timer_check_pkts: Invalid IO found. iotag=%x", + iotag); + + hba->fc_table[iotag] = STALE_PACKET; + hba->io_count--; + continue; + } + + if ((sbp->pkt_flags & PACKET_IN_CHIPQ) && (hba->timer_tics >= sbp->ticks)) { rc = emlxs_pkt_chip_timeout(sbp->iocbq.port, sbp, &abort, flag); @@ -806,7 +822,7 @@ emlxs_timer_check_heartbeat(emlxs_hba_t *hba) rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } return; @@ -828,9 +844,15 @@ emlxs_timer_check_fw_update(emlxs_hba_t *hba) return; } - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg, - "A manual HBA reset or link reset (using luxadm or fcadm) " - "is required."); + if (hba->tgt_mode) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg, + "A manual HBA reset or link reset (using emlxadm) " + "is required."); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg, + "A manual HBA reset or link reset (using luxadm or fcadm) " + "is required."); + } /* Set timer for 24 hours */ hba->fw_timer = hba->timer_tics + (60 * 60 * 24); @@ -896,7 +918,7 @@ emlxs_timer_check_discovery(emlxs_port_t *port) mutex_exit(&EMLXS_PORT_LOCK); - (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, NULL, NULL, NULL); + (void) emlxs_mb_unreg_node(port, nlp, NULL, NULL, NULL); mutex_enter(&EMLXS_PORT_LOCK); @@ -914,7 +936,7 @@ emlxs_timer_check_discovery(emlxs_port_t *port) */ if (hba->state != FC_LINK_UP) { mutex_exit(&EMLXS_PORT_LOCK); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } else { /* Change state and clear discovery timer */ EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA); @@ -928,8 +950,7 @@ emlxs_timer_check_discovery(emlxs_port_t *port) rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } } } @@ -1033,7 +1054,8 @@ emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abortq, /* Create the abort IOCB */ if (hba->state >= FC_LINK_UP) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg, - "chipQ:1:Aborting. sbp=%p iotag=%x tmo=%d flags=%x", + "chipQ: 1:Aborting. sbp=%p iotag=%x tmo=%d " + "flags=%x", sbp, sbp->iotag, (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags); @@ -1047,7 +1069,8 @@ emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abortq, hba->timer_tics + (4 * hba->fc_ratov) + 10; } else { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg, - "chipQ:1:Closing. sbp=%p iotag=%x tmo=%d flags=%x", + "chipQ: 1:Closing. sbp=%p iotag=%x tmo=%d " + "flags=%x", sbp, sbp->iotag, (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags); diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dfc.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dfc.c index 82ff99ffb9..34df2de4ad 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dfc.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dfc.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -315,16 +315,16 @@ emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode) dfc->cmd = dfc32.cmd; dfc->flag = dfc32.flag; - dfc->buf1 = (void *)((unsigned long)dfc32.buf1); + dfc->buf1 = (void *)((uintptr_t)dfc32.buf1); dfc->buf1_size = dfc32.buf1_size; dfc->data1 = dfc32.data1; - dfc->buf2 = (void *)((unsigned long)dfc32.buf2); + dfc->buf2 = (void *)((uintptr_t)dfc32.buf2); dfc->buf2_size = dfc32.buf2_size; dfc->data2 = dfc32.data2; - dfc->buf3 = (void *)((unsigned long)dfc32.buf3); + dfc->buf3 = (void *)((uintptr_t)dfc32.buf3); dfc->buf3_size = dfc32.buf3_size; dfc->data3 = dfc32.data3; - dfc->buf4 = (void *)((unsigned long)dfc32.buf4); + dfc->buf4 = (void *)((uintptr_t)dfc32.buf4); dfc->buf4_size = dfc32.buf4_size; dfc->data4 = dfc32.data4; @@ -980,7 +980,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_cmd_code = FC_PORT_DIAG; pm.pm_cmd_flags = fcio->fcio_cmd_flags; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1084,7 +1084,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) bzero(null_wwn, 8); if (bcmp((uint8_t *)fcio->fcio_ibuf, null_wwn, 8) == 0) { - rval = emlxs_reset(port, FC_FCA_LINK_RESET); + rval = emlxs_fca_reset(port, FC_FCA_LINK_RESET); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1099,7 +1099,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) case FCIO_RESET_HARD: case FCIO_RESET_HARD_CORE: { - rval = emlxs_reset(port, FC_FCA_RESET); + rval = emlxs_fca_reset(port, FC_FCA_RESET); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1113,7 +1113,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) fc_fca_pm_t pm; if (fcio->fcio_xfer != FCIO_XFER_WRITE || - fcio->fcio_ilen <= 0) { + fcio->fcio_ilen == 0) { rval = EINVAL; break; } @@ -1125,7 +1125,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_ilen; pm.pm_data_buf = fcio->fcio_ibuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1151,7 +1151,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_olen; pm.pm_data_buf = fcio->fcio_obuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1177,7 +1177,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_olen; pm.pm_data_buf = fcio->fcio_obuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1191,7 +1191,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) fc_fca_pm_t pm; if (fcio->fcio_xfer != FCIO_XFER_WRITE || - fcio->fcio_ilen <= 0) { + fcio->fcio_ilen == 0) { rval = EINVAL; break; } @@ -1203,7 +1203,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_ilen; pm.pm_data_buf = fcio->fcio_ibuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1580,7 +1580,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_olen; pm.pm_data_buf = fcio->fcio_obuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1606,7 +1606,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = fcio->fcio_ilen; pm.pm_data_buf = fcio->fcio_ibuf; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -1915,7 +1915,7 @@ emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) pm.pm_data_len = sizeof (fc_rls_acc_t); pm.pm_data_buf = (caddr_t)rls; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -2143,7 +2143,7 @@ get_node_attrs: case FCIO_FORCE_DUMP: { - rval = emlxs_reset(port, FC_FCA_CORE); + rval = emlxs_fca_reset(port, FC_FCA_CORE); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -2171,7 +2171,7 @@ get_node_attrs: pm.pm_cmd_code = FC_PORT_GET_DUMP_SIZE; pm.pm_cmd_flags = FC_FCA_PM_READ; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -2203,7 +2203,7 @@ get_node_attrs: pm.pm_cmd_code = FC_PORT_GET_DUMP_SIZE; pm.pm_cmd_flags = FC_FCA_PM_READ; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -2229,7 +2229,7 @@ get_node_attrs: pm.pm_cmd_code = FC_PORT_GET_DUMP; pm.pm_cmd_flags = FC_FCA_PM_READ; - rval = emlxs_port_manage(port, &pm); + rval = emlxs_fca_port_manage(port, &pm); if (rval != FC_SUCCESS) { fcio->fcio_errno = rval; @@ -2447,7 +2447,7 @@ emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) /* Generate new WWPN */ bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport.wwpn, 8); dfc_vport.wwpn[0] = 0x20; - dfc_vport.wwpn[1] = vpi; + dfc_vport.wwpn[1] = (uint8_t)vpi; } else { /* use one provided */ /* Make sure WWPN is unique */ @@ -2468,7 +2468,7 @@ emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) /* Generate new WWNN */ bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport.wwnn, 8); dfc_vport.wwnn[0] = 0x28; - dfc_vport.wwnn[1] = vpi; + dfc_vport.wwnn[1] = (uint8_t)vpi; } /* else use WWNN provided */ @@ -2837,12 +2837,12 @@ emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) total_rpi = 0; for (i = 0; i < hba->sli.sli4.VPICount; i++) { vport = &VPORT(i); - total_rpi += vport->outstandingRPIs; + total_rpi += vport->VPIobj.rpi_online; } vres.vpi_max = hba->sli.sli4.VPICount - 1; - vres.vpi_inuse = (port->VFIp == NULL) ? 0 : - port->VFIp->outstandingVPIs - 1; + vres.vpi_inuse = (port->VPIobj.vfip == NULL) ? 0 : + (port->VPIobj.vfip->vpi_online - 1); vres.rpi_max = hba->sli.sli4.RPICount; vres.rpi_inuse = total_rpi; @@ -3154,11 +3154,10 @@ emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) * Free up default RPIs and VPI */ free_resc: - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - (void) emlxs_sli4_unreg_all_rpi_by_port(vport); - } else { - (void) emlxs_mb_unreg_rpi(vport, 0xffff, 0, 0, 0); - } + + /* Unregister all nodes */ + (void) emlxs_mb_unreg_node(vport, 0, 0, 0, 0); + (void) emlxs_mb_unreg_vpi(vport); done: @@ -4644,7 +4643,7 @@ done: } } #endif /* FMA_SUPPORT */ - (void) emlxs_mem_buf_free(hba, rx_mp); + emlxs_mem_buf_free(hba, rx_mp); } if (tx_mp) { @@ -4660,7 +4659,7 @@ done: } } #endif /* FMA_SUPPORT */ - (void) emlxs_mem_buf_free(hba, tx_mp); + emlxs_mem_buf_free(hba, tx_mp); } return (rval); @@ -5516,7 +5515,7 @@ emlxs_send_menlo_cmd(emlxs_hba_t *hba, uint8_t *cmd_buf, uint32_t cmd_size, uint8_t *data_buf = NULL; uint32_t data_size = 0; fc_packet_t *pkt = NULL; - uint32_t rval = 0; + int32_t rval = 0; menlo_set_cmd_t set_cmd; menlo_reset_cmd_t reset_cmd; uint32_t rsp_code; @@ -8548,7 +8547,7 @@ static int32_t emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) { emlxs_port_t *port = &PPORT; - uint32_t rval = 0; + int32_t rval = 0; NODELIST *ndlp; clock_t timeout; fc_packet_t *pkt = NULL; @@ -8764,7 +8763,7 @@ done: mutex_exit(&EMLXS_PKT_LOCK); /* Reset the adapter */ - (void) emlxs_reset(port, FC_FCA_LINK_RESET); + (void) emlxs_fca_reset(port, FC_FCA_LINK_RESET); } if (pkt) { @@ -10267,7 +10266,7 @@ emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) emlxs_port_t *port = &PPORT; DFC_FCoEFCFInfo_t *fcflistentry; DFC_FCoEFCFList_t *fcflist; - FCFIobj_t *fp; + FCFIobj_t *fcfp; uint32_t size; uint32_t i; uint32_t count = 0; @@ -10303,7 +10302,7 @@ emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) } size = sizeof (DFC_FCoEFCFList_t) + - hba->sli.sli4.FCFICount * sizeof (DFC_FCoEFCFInfo_t); + hba->sli.sli4.fcftab.table_count * sizeof (DFC_FCoEFCFInfo_t); fcflist = (DFC_FCoEFCFList_t *)kmem_zalloc(size, KM_SLEEP); if (ddi_copyin(dfc->buf1, (void *)fcflist, @@ -10316,40 +10315,43 @@ emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) } fcflistentry = fcflist->entries; - mutex_enter(&hba->sli.sli4.id_lock); - fp = hba->sli.sli4.FCFIp; - for (i = 0; i < hba->sli.sli4.FCFICount; i ++) { - if ((fp->state == RESOURCE_ALLOCATED) && - (fp->fcf_rec.fcf_valid)) { - fcflistentry->Priority = fp->fcf_rec.fip_priority; - if (fp->fcf_rec.fcf_available) + mutex_enter(&EMLXS_FCF_LOCK); + fcfp = hba->sli.sli4.fcftab.table; + for (i = 0; i < hba->sli.sli4.fcftab.table_count; i++, fcfp++) { + if ((fcfp->state != FCFI_STATE_FREE) && + (fcfp->fcf_rec.fcf_valid)) { + fcflistentry->Priority = fcfp->fcf_rec.fip_priority; + if (fcfp->fcf_rec.fcf_available) { fcflistentry->State = FCF_AVAILABLE_STATE; - fcflistentry->LKA_Period = fp->fcf_rec.fka_adv_period; + } + fcflistentry->LKA_Period = fcfp->fcf_rec.fka_adv_period; - bcopy((void *)fp->fcf_rec.vlan_bitmap, + bcopy((void *)fcfp->fcf_rec.vlan_bitmap, (void *)fcflistentry->VLanBitMap, 512); - bcopy((void *)fp->fcf_rec.fc_map, + bcopy((void *)fcfp->fcf_rec.fc_map, (void *)fcflistentry->FC_Map, 3); - bcopy((void *)fp->fcf_rec.fabric_name_identifier, + bcopy((void *)fcfp->fcf_rec.fabric_name_identifier, (void *)fcflistentry->FabricName, 8); - bcopy((void *)fp->fcf_rec.switch_name_identifier, + bcopy((void *)fcfp->fcf_rec.switch_name_identifier, (void *)fcflistentry->SwitchName, 8); - bcopy((void *)&fp->fcf_rec.fcf_mac_address_hi, + bcopy((void *)&fcfp->fcf_rec.fcf_mac_address_hi, (void *)fcflistentry->Mac, 6); - count ++; - fcflistentry ++; + count++; + fcflistentry++; } - fp ++; } - mutex_exit(&hba->sli.sli4.id_lock); + mutex_exit(&EMLXS_FCF_LOCK); - if (count > fcflist->numberOfEntries) + fcflist->nActiveFCFs = hba->sli.sli4.fcftab.fcfi_count; + + if (count > fcflist->numberOfEntries) { rval = DFC_ARG_TOOSMALL; + } i = sizeof (DFC_FCoEFCFList_t) + (fcflist->numberOfEntries - 1) * sizeof (DFC_FCoEFCFInfo_t); - fcflist->numberOfEntries = count; + fcflist->numberOfEntries = (uint16_t)count; if (ddi_copyout((void *) fcflist, dfc->buf1, i, mode) != 0) { @@ -10517,16 +10519,17 @@ done: static int emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) { - emlxs_port_t *port = &PPORT; - MATCHMAP *mp; - MAILBOX4 *mb = NULL; - MAILBOXQ *mbq = NULL; - IOCTL_FCOE_READ_FCF_TABLE *fcf; - mbox_req_hdr_t *hdr_req; - FCF_RECORD_t *fcfrec; - int32_t rc = 0; - uint32_t rval = 0; - uint16_t index; + emlxs_port_t *port = &PPORT; + MATCHMAP *mp; + MAILBOX4 *mb = NULL; + MAILBOXQ *mbq = NULL; + IOCTL_FCOE_READ_FCF_TABLE *fcf; + mbox_req_hdr_t *hdr_req; + mbox_rsp_hdr_t *hdr_rsp; + FCF_RECORD_t *fcfrec; + uint32_t rc = 0; + uint32_t rval = 0; + uint16_t index; if (!dfc->buf1 || !dfc->buf1_size) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, @@ -10547,18 +10550,21 @@ emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) rval = DFC_SYSRES_ERROR; goto done; } + bzero(mp->virt, mp->size); + /* - * Save address for completion * Signifies a non-embedded command */ mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; mb->mbxOwner = OWN_HOST; hdr_req = (mbox_req_hdr_t *)mp->virt; + hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; + hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE; hdr_req->timeout = 0; @@ -10582,11 +10588,17 @@ emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd), emlxs_mb_cmd_xlate(mb->mbxCommand), rc); - rval = DFC_COPYOUT_ERROR; + + if ((rc == MBX_NONEMBED_ERROR) && + (hdr_rsp->status == MBX_RSP_STATUS_NO_FCF)) { + rval = DFC_FCOE_NO_DATA; + } else { + rval = DFC_IO_ERROR; + } } done: if (mp) - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); if (mbq) kmem_free(mbq, sizeof (MAILBOXQ)); @@ -10627,7 +10639,7 @@ emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_DCBX_SET_DCBX_MODE); dcbx_mode = (IOCTL_DCBX_SET_DCBX_MODE *)&mb->un.varSLIConfig.payload; - dcbx_mode->params.request.port_num = port_num; + dcbx_mode->params.request.port_num = (uint8_t)port_num; dcbx_mode->params.request.dcbx_mode = dfc->data1; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, @@ -10681,7 +10693,7 @@ emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_DCBX_SET_DCBX_MODE); dcbx_mode = (IOCTL_DCBX_GET_DCBX_MODE *)&mb->un.varSLIConfig.payload; - dcbx_mode->params.request.port_num = port_num; + dcbx_mode->params.request.port_num = (uint8_t)port_num; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num); @@ -10734,4 +10746,5 @@ emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) } return (rval); -} + +} /* emlxs_dfc_get_qos() */ diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c index dd8dd5202c..9b42ca95b6 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -117,10 +117,7 @@ static fc_packet_t *emlxs_prep_els_fc_pkt(emlxs_port_t *port, static uint32_t *emlxs_hash_vrf(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc, NODELIST *ndlp, uint32_t tran_id, union challenge_val un_cval); -static void emlxs_md5_digest_to_hex(const uint8_t digest[MD5_LEN], - char *output); -static void emlxs_sha1_digest_to_hex(const uint8_t digest[SHA1_LEN], - char *output); + static BIG_ERR_CODE emlxs_interm_hash(emlxs_port_t *port, emlxs_port_dhc_t *port_dhc, @@ -210,26 +207,10 @@ emlxs_rcv_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t *port, static uint32_t emlxs_cmpl_auth_msg_dhchap_success_cmpl_wait4next(emlxs_port_t *port, void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_rm_plogi_issue(emlxs_port_t *port, void *arg1, - void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_recov_plogi_issue(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_rm_adisc_issue(emlxs_port_t *port, void *arg1, - void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_recov_adisc_issue(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_rm_reglogin_issue(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_recov_reglogin_issue(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_rm_prli_issue(emlxs_port_t *port, void *arg1, - void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_recov_prli_issue(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); + + static uint32_t emlxs_device_recov_unmapped_node(emlxs_port_t *port, void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); -static uint32_t emlxs_device_recov_mapped_node(emlxs_port_t *port, - void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); static uint32_t emlxs_device_rm_npr_node(emlxs_port_t *port, void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); static uint32_t emlxs_device_recov_npr_node(emlxs_port_t *port, void *arg1, @@ -239,6 +220,10 @@ static uint32_t emlxs_device_rem_auth(emlxs_port_t *port, void *arg1, static uint32_t emlxs_device_recov_auth(emlxs_port_t *port, void *arg1, void *arg2, void *arg3, void *arg4, uint32_t evt); +static uint8_t emlxs_null_wwn[8] = + {0, 0, 0, 0, 0, 0, 0, 0}; +static uint8_t emlxs_fabric_wwn[8] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; unsigned char dhgp1_pVal[] = {0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, 0x0A, 0xFA, @@ -442,7 +427,7 @@ emlxs_dhc_state(emlxs_port_t *port, emlxs_node_t *ndlp, uint32_t state, emlxs_dhc_nstate_xlate(state)); node_dhc->prev_state = node_dhc->state; - node_dhc->state = state; + node_dhc->state = (uint16_t)state; /* Perform common functions based on state */ switch (state) { @@ -4070,173 +4055,6 @@ uint32_t evt) /* ARGSUSED */ static uint32_t -emlxs_device_rm_plogi_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "device_rm_plogi_issue called. did=0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_rm_plogi_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_recov_plogi_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_recov_plogi_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_recov_plogi_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_rm_adisc_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *) arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_rm_adisc_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_rm_adisc_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_recov_adisc_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_recov_adisc_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_recov_adisc_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_rm_reglogin_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_rm_reglogin_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_rm_reglogin_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_recov_reglogin_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_recov_reglogin_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_recov_reglogin_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_rm_prli_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_rm_prli_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_rm_prli_issue */ - - -/* ARGSUSED */ -static uint32_t -emlxs_device_recov_prli_issue( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_recov_prli_issue called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_recov_prli_issue */ - -/* ARGSUSED */ -static uint32_t emlxs_device_recov_unmapped_node( emlxs_port_t *port, void *arg1, @@ -4255,25 +4073,6 @@ emlxs_device_recov_unmapped_node( } /* emlxs_device_recov_unmapped_node */ -/* ARGSUSED */ -static uint32_t -emlxs_device_recov_mapped_node( - emlxs_port_t *port, - void *arg1, - void *arg2, - void *arg3, - void *arg4, - uint32_t evt) -{ - NODELIST *ndlp = (NODELIST *)arg4; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcsp_error_msg, - "emlxs_device_recov_mapped_node called. 0x%x. Not implemented.", - ndlp->nlp_DID); - - return (0); - -} /* emlxs_device_recov_mapped_node */ /* ARGSUSED */ @@ -5211,42 +5010,6 @@ AUTH_Reject: } /* emlxs_rcv_auth_msg_unmapped_node */ -void -emlxs_sha1_digest_to_hex(const uint8_t digest[SHA1_LEN], char *output) -{ - int i, j; - char *c = output; - - for (i = 0; i < SHA1_LEN / 4; i++) { - for (j = 0; j < 4; j++) { - (void) sprintf(c, "%02X", digest[i * 4 + j]); - c += 2; - } - (void) sprintf(c, " "); - c += 1; - } - *(c - 1) = '\0'; - -} /* emlxs_sha1_digest_to_hex */ - - -static void -emlxs_md5_digest_to_hex(const uint8_t digest[MD5_LEN], char *output) -{ - int i, j; - char *c = output; - - for (i = 0; i < MD5_LEN / 4; i++) { - for (j = 0; j < 4; j++) { - (void) sprintf(c, "%02X", digest[i * 4 + j]); - c += 2; - } - (void) sprintf(c, " "); - c += 1; - } - *(c - 1) = '\0'; - -} /* emlxs_md5_digest_to_hex */ /* @@ -7490,8 +7253,6 @@ emlxs_dhc_auth_complete( uint32_t status) { emlxs_node_dhc_t *node_dhc = &ndlp->node_dhc; - emlxs_buf_t *sbp; - fc_unsol_buf_t *ubp; uint32_t fabric; uint32_t fabric_switch; @@ -7521,28 +7282,15 @@ emlxs_dhc_auth_complete( ndlp->nlp_DID); emlxs_send_logo(port, ndlp->nlp_DID); } - /* If a packet is being held then complete it now */ - if ((sbp = (emlxs_buf_t *)node_dhc->deferred_sbp) != 0) { - node_dhc->deferred_sbp = 0; - if (status != 0) { - /* Set error status */ - sbp->pkt_flags &= ~PACKET_STATE_VALID; - emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, - IOERR_NO_RESOURCES, 1); - } - emlxs_pkt_complete(sbp, -1, 0, 1); - } - /* If a buffer is being held then handle it now */ - if ((ubp = (fc_unsol_buf_t *)node_dhc->deferred_ubp) != 0) { - node_dhc->deferred_ubp = 0; + /* Process deferred cmpl now */ + emlxs_mb_deferred_cmpl(port, status, + (emlxs_buf_t *)node_dhc->deferred_sbp, + (fc_unsol_buf_t *)node_dhc->deferred_ubp, 0); + + node_dhc->deferred_sbp = 0; + node_dhc->deferred_ubp = 0; - if (status == 0) { - emlxs_ub_callback(port, ubp); - } else { - (void) emlxs_ub_release(port, 1, &ubp->ub_token); - } - } return; } /* emlxs_dhc_auth_complete */ @@ -8373,7 +8121,7 @@ emlxs_auth_cfg_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -8415,7 +8163,7 @@ emlxs_auth_cfg_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -9021,7 +8769,7 @@ emlxs_auth_key_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -9063,7 +8811,7 @@ emlxs_auth_key_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -9092,7 +8840,7 @@ emlxs_auth_key_parse( } } while (*s != ':' && *s != 0); - auth_key->local_password_type = sum; + auth_key->local_password_type = (uint16_t)sum; if (*s++ != ':') { EMLXS_MSGF(EMLXS_CONTEXT, @@ -9143,7 +8891,7 @@ emlxs_auth_key_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; j++; } while (*s != ':' && *s != 0); @@ -9163,7 +8911,7 @@ emlxs_auth_key_parse( errors++; goto out; } - auth_key->local_password_length = j; + auth_key->local_password_length = (uint16_t)j; if (*s++ != ':') { EMLXS_MSGF(EMLXS_CONTEXT, @@ -9191,7 +8939,7 @@ emlxs_auth_key_parse( } } while (*s != ':' && *s != 0); - auth_key->remote_password_type = sum; + auth_key->remote_password_type = (uint16_t)sum; if (*s++ != ':') { EMLXS_MSGF(EMLXS_CONTEXT, @@ -9242,7 +8990,7 @@ emlxs_auth_key_parse( errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; j++; } while (*s != ':' && *s != 0); @@ -9262,7 +9010,7 @@ emlxs_auth_key_parse( errors++; goto out; } - auth_key->remote_password_length = j; + auth_key->remote_password_length = (uint16_t)j; if (errors) { goto out; diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_diag.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_diag.c index eaef06e270..ea4f08112a 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_diag.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_diag.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -407,7 +407,7 @@ done: rval = EMLXS_TEST_FAILED; } #endif /* FMA_SUPPORT */ - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); } if (mp1) { #ifdef FMA_SUPPORT @@ -420,10 +420,10 @@ done: rval = EMLXS_TEST_FAILED; } #endif /* FMA_SUPPORT */ - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); + emlxs_mem_put(hba, MEM_BUF, (void *)mp1); } if (mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } return (rval); diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c index 3824d24aed..80539daed3 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c @@ -98,6 +98,7 @@ static void emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr); static void emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image); + static uint32_t emlxs_type_check(uint32_t type); static uint32_t emlxs_kern_check(emlxs_hba_t *hba, uint32_t version); @@ -119,11 +120,12 @@ static uint32_t emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version); static uint32_t emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id, uint32_t type, char *file_type); -static uint32_t emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, +static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, emlxs_be_fw_image_t *fw_image); -static int32_t emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer, - emlxs_be_fw_file_t *file, - MAILBOXQ *mbq, MATCHMAP *mp); +static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer, + uint32_t len, emlxs_be_fw_image_t *fw_image); + + static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba, emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp); @@ -131,7 +133,8 @@ static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer, emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp); static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, uint32_t offline); - +static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size, + uint32_t *plus_flag); static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image); static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId); @@ -353,7 +356,7 @@ done: } /* emlxs_fw_download */ -static void +extern void emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size) { while (size--) { @@ -401,7 +404,7 @@ emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer, xfer_size = min(BE_MAX_XFER_SIZE, block_size); mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -433,10 +436,9 @@ emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer, image_ptr += count; } - /* Set last three words of last payload with */ - /* load address, image size and block crc */ if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) { wptr = (uint32_t *)&payload[(xfer_size - 12)]; + wptr[0] = file->load_address; wptr[1] = file->image_size; wptr[2] = file->block_crc; @@ -465,131 +467,6 @@ done: } /* emlxs_sli4_flash_image() */ -static int32_t -emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer, - emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp) -{ - emlxs_port_t *port = &PPORT; - uint8_t *image_ptr; - uint32_t *wptr; - uint32_t *wptr1; - uint8_t *payload; - MAILBOX4 *mb; - IOCTL_COMMON_FLASHROM *flashrom; - mbox_req_hdr_t *hdr_req; - uint32_t xfer_size; - uint32_t block_size; - uint32_t block_offset; - uint32_t rval = 0; - uint32_t i; - char signature[BE_SIGNATURE_SIZE]; - uint32_t ufi_plus = 0; - - /* Check for special deflated format */ - (void) sprintf(signature, "%s+", BE_SIGNATURE); - if (strncmp(signature, buffer, - sizeof (signature)-1) == 0) { - ufi_plus = 1; - } - - image_ptr = (uint8_t *)buffer + file->image_offset; - block_size = (ufi_plus)? file->image_size: file->block_size; - block_offset = 0; - mb = (MAILBOX4*)mbq; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%s: Verifying image...", file->label); - - while (block_size) { - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - bzero((void *) mp->virt, mp->size); - - xfer_size = min(BE_MAX_XFER_SIZE, block_size); - - mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; - mbq->mbox_cmpl = NULL; - - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - - hdr_req = (mbox_req_hdr_t *)mp->virt; - hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; - hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM; - hdr_req->timeout = 0; - hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + - xfer_size; - - flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); - flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT; - flashrom->params.optype = file->type; - flashrom->params.data_buffer_size = xfer_size; - flashrom->params.offset = block_offset; - - /* Send read request */ - if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != - MBX_SUCCESS) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%s: Unable to read image. status=%x", - file->label, mb->mbxStatus); - - rval = EMLXS_IMAGE_FAILED; - goto done; - } - - payload = (uint8_t *)(&flashrom->params.data_buffer); - - BE_SWAP32_BUFFER(payload, xfer_size); - - wptr = (uint32_t *)image_ptr; - wptr1 = (uint32_t *)payload; - for (i = 0; i < xfer_size; i += 4, wptr++, wptr1++) { - if (*wptr != *wptr1) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%s: Image mismatch. [%08x] %x, %x", - file->label, i, - BE_MAX_XFER_SIZE, xfer_size); - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%08x: %08x %08x %08x %08x %08x " \ - "%08x %08x %08x", - i, wptr[0], wptr[1], wptr[2], - wptr[3], wptr[4], wptr[5], wptr[6], - wptr[7]); - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%08x: %08x %08x %08x %08x %08x " \ - "%08x %08x %08x", - i, wptr1[0], wptr1[1], wptr1[2], - wptr1[3], wptr1[4], wptr1[5], wptr1[6], - wptr1[7]); - - rval = EMLXS_IMAGE_FAILED; - goto done; - } - } - - bcopy((uint8_t *)(&flashrom->params.data_buffer), image_ptr, - xfer_size); - - block_size -= xfer_size; - block_offset += xfer_size; - image_ptr += xfer_size; - } - - /* Verify CRC */ - rval = emlxs_sli4_verify_crc(hba, file, mbq, mp); - -done: - - if (rval == 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%s: Image verified.", file->label); - } - - return (rval); - -} /* emlxs_sli4_verify_image() */ static int32_t @@ -618,7 +495,7 @@ emlxs_sli4_verify_crc(emlxs_hba_t *hba, bzero((void *) mp->virt, mp->size); mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -644,7 +521,7 @@ emlxs_sli4_verify_crc(emlxs_hba_t *hba, "%s: Unable to read CRC. status=%x", file->label, mb->mbxStatus); - rval = EMLXS_IMAGE_FAILED; + rval = 2; goto done; } @@ -658,7 +535,7 @@ emlxs_sli4_verify_crc(emlxs_hba_t *hba, "%s: Image size mismatch. %08x != %08x", file->label, value, file->image_size); - rval = EMLXS_IMAGE_FAILED; + rval = 1; goto done; } @@ -668,7 +545,7 @@ emlxs_sli4_verify_crc(emlxs_hba_t *hba, EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, "%s: CRC mismatch. %08x != %08x", file->label, value, file->block_crc); - rval = EMLXS_IMAGE_FAILED; + rval = 1; } done: @@ -728,7 +605,7 @@ emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw) bzero((void *) mp->virt, mp->size); mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -774,7 +651,7 @@ emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw) bzero((void *) mp->virt, mp->size); mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -814,11 +691,11 @@ emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw) done: if (mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } if (mp) { - (void) emlxs_mem_buf_free(hba, mp); + emlxs_mem_buf_free(hba, mp); } return (rval); @@ -827,13 +704,53 @@ done: static uint32_t -emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, +emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag) +{ + emlxs_be2_ufi_header_t *ufi_hdr; + char signature[BE2_SIGNATURE_SIZE]; + uint32_t be_version = 0; + + if (size < sizeof (emlxs_be2_ufi_header_t)) { + return (0); + } + ufi_hdr = (emlxs_be2_ufi_header_t *)buffer; + + (void) sprintf(signature, "%s+", BE_SIGNATURE); + + /* Check if this is a UFI image */ + if (strncmp(signature, (char *)ufi_hdr->signature, + strlen(BE_SIGNATURE)) != 0) { + return (0); + } + + /* Check if this is a UFI plus image */ + if (plus_flag) { + /* Check if this is a UFI plus image */ + if (strncmp(signature, (char *)ufi_hdr->signature, + strlen(BE_SIGNATURE)+1) == 0) { + *plus_flag = 1; + } else { + *plus_flag = 0; + } + } + + if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) { + be_version = ufi_hdr->build[0] - '0'; + } + + return (be_version); + +} /* emlxs_be_version() */ + + +static uint32_t +emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, emlxs_be_fw_image_t *fw_image) { emlxs_port_t *port = &PPORT; - emlxs_sli4_ufi_header_t *ufi_hdr; - emlxs_sli4_flash_dir_t *flash_dir; - emlxs_sli4_flash_entry_t *entry; + emlxs_be2_ufi_header_t *ufi_hdr; + emlxs_be2_flash_dir_t *flash_dir; + emlxs_be2_flash_entry_t *entry; uint8_t *bptr; uint32_t *wptr; uint32_t i; @@ -843,41 +760,37 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t image_size; emlxs_be_fw_file_t *file; emlxs_be_fw_file_t *file2; - char signature[BE_SIGNATURE_SIZE]; uint32_t ufi_plus = 0; + uint32_t be_version = 0; + uint32_t found; bzero(fw_image, sizeof (emlxs_be_fw_image_t)); - if (hba->model_info.chip != EMLXS_BE_CHIP) { + if (hba->model_info.chip != EMLXS_BE2_CHIP) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, "Invalid adapter model."); return (EMLXS_IMAGE_INCOMPATIBLE); } - if (len < (sizeof (emlxs_sli4_ufi_header_t) + - sizeof (emlxs_sli4_flash_dir_t))) { + if (len < (sizeof (emlxs_be2_ufi_header_t) + + sizeof (emlxs_be2_flash_dir_t))) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, "Image too small. (%d < %d)", - len, (sizeof (emlxs_sli4_ufi_header_t) + - sizeof (emlxs_sli4_flash_dir_t))); + len, (sizeof (emlxs_be2_ufi_header_t) + + sizeof (emlxs_be2_flash_dir_t))); return (EMLXS_IMAGE_BAD); } - ufi_hdr = (emlxs_sli4_ufi_header_t *)buffer; - /* Check if this is a standard UFI image */ - if (strncmp(BE_SIGNATURE, ufi_hdr->signature, - sizeof (BE_SIGNATURE)-1) != 0) { + be_version = emlxs_be_version(buffer, len, &ufi_plus); + + /* Check if this is a standard BE2 image */ + if (be_version != 2) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, "Invalid image provided."); return (EMLXS_IMAGE_INCOMPATIBLE); } - /* Check for special deflated format */ - (void) sprintf(signature, "%s+", BE_SIGNATURE); - if (strncmp(signature, ufi_hdr->signature, - sizeof (signature)-1) == 0) { - ufi_plus = 1; - } + ufi_hdr = (emlxs_be2_ufi_header_t *)buffer; #ifdef EMLXS_BIG_ENDIAN /* Big Endian Swapping */ @@ -918,7 +831,7 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, for (i = 0; i < len; i++, bptr++) { if (strncmp((char *)bptr, BE_DIR_SIGNATURE, sizeof (BE_DIR_SIGNATURE)) == 0) { - flash_dir = (emlxs_sli4_flash_dir_t *)bptr; + flash_dir = (emlxs_be2_flash_dir_t *)bptr; break; } } @@ -971,7 +884,10 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, } entry = &flash_dir->entry[i]; - if (entry->image_size == 0) { + + if ((entry->type == 0) || + (entry->type == (uint32_t)-1) || + (entry->image_size == 0)) { continue; } @@ -994,7 +910,25 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, } #endif /* EMLXS_BIG_ENDIAN */ + /* Verify adapter model */ + found = 0; + for (i = 0; i < BE_CONTROLLER_SIZE; i++) { + if (flash_dir->header.controller[i].device_id == + hba->model_info.device_id) { + found = 1; + } + } + + if (!found) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid adapter device id=0x%x.", + hba->model_info.device_id); + return (EMLXS_IMAGE_INCOMPATIBLE); + } + /* Build fw_image table */ + fw_image->be_version = 2; + fw_image->ufi_plus = ufi_plus; for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) { if (!(flash_dir->header.valid_entry_mask & mask)) { @@ -1002,7 +936,10 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, } entry = &flash_dir->entry[i]; - if (entry->image_size == 0) { + + if ((entry->type == 0) || + (entry->type == (uint32_t)-1) || + (entry->image_size == 0)) { continue; } @@ -1048,6 +985,8 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, continue; } + file->be_version = fw_image->be_version; + file->ufi_plus = fw_image->ufi_plus; file->image_size = entry->image_size; image_size = BE_SWAP32(entry->image_size); @@ -1056,9 +995,10 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, file->block_size = entry->pad_size; file->block_crc = entry->checksum; file->load_address = entry->entry_point; + } else { file->image_offset = entry->offset + - sizeof (emlxs_sli4_ufi_header_t); + sizeof (emlxs_be2_ufi_header_t); /* Get entry block size and crc */ k = file->image_offset + file->image_size; @@ -1106,34 +1046,388 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, /* Automatically create a backup file entry for firmware */ if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) { file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE]; - (void) strcpy(file2->label, "FCOE BACKUP"); + + bcopy((uint8_t *)file, (uint8_t *)file2, + sizeof (emlxs_be_fw_file_t)); file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP; - file2->image_offset = file->image_offset; - file2->image_size = file->image_size; - file2->block_size = file->block_size; - file2->block_crc = file->block_crc; - file2->load_address = file->load_address; + (void) strcpy(file2->label, "FCOE BACKUP"); /* Save FCOE version info */ bptr = (uint8_t *)buffer + file->image_offset + 0x30; - (void) strncpy(fw_image->label, (char *)bptr, + (void) strncpy(fw_image->fcoe_label, (char *)bptr, BE_VERSION_SIZE); - fw_image->version = file->block_crc; + fw_image->fcoe_version = file->block_crc; } else if (file->type == MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) { file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE]; + + bcopy((uint8_t *)file, (uint8_t *)file2, + sizeof (emlxs_be_fw_file_t)); + file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP; (void) strcpy(file2->label, "ISCSI BACKUP"); + + /* Save ISCSI version info */ + bptr = (uint8_t *)buffer + file->image_offset + 0x30; + (void) strncpy(fw_image->iscsi_label, (char *)bptr, + BE_VERSION_SIZE); + fw_image->iscsi_version = file->block_crc; + } + } + + if (fw_image->fcoe_version == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Unable to find FCOE firmware component."); + + bzero(fw_image, sizeof (emlxs_be_fw_image_t)); + return (EMLXS_IMAGE_BAD); + } + + /* Display contents */ + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, + "BE2 UFI Image: %08x, %s", fw_image->fcoe_version, + fw_image->fcoe_label); + + for (i = 0; i < BE_MAX_FLASHTYPES; i++) { + file = &fw_image->file[i]; + + if (file->image_size == 0) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, + "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x " + "load=%x", + file->label, file->be_version, (file->ufi_plus)?"+":"", + file->type, file->block_size, file->image_size, + file->image_offset, file->block_crc, file->load_address); + } + + return (0); + +} /* emlxs_be2_validate_image() */ + + +static uint32_t +emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer, + uint32_t len, emlxs_be_fw_image_t *fw_image) +{ + emlxs_port_t *port = &PPORT; + emlxs_be3_ufi_header_t *ufi_hdr; + emlxs_be3_flash_dir_t *flash_dir; + emlxs_be3_flash_entry_t *entry; + emlxs_be3_image_header_t *flash_image_hdr; + emlxs_be3_image_header_t *image_hdr; + uint8_t *bptr; + uint32_t *wptr; + uint32_t i; + uint32_t value; + emlxs_be_fw_file_t *file; + emlxs_be_fw_file_t *file2; + uint32_t ufi_plus = 0; + uint32_t be_version = 0; + uint32_t found; + + bzero(fw_image, sizeof (emlxs_be_fw_image_t)); + + if (hba->model_info.chip != EMLXS_BE3_CHIP) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid adapter model."); + return (EMLXS_IMAGE_INCOMPATIBLE); + } + + if (len < (sizeof (emlxs_be3_ufi_header_t) + + sizeof (emlxs_be3_flash_dir_t))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Image too small. (%d < %d)", + len, (sizeof (emlxs_be3_ufi_header_t) + + sizeof (emlxs_be3_flash_dir_t))); + return (EMLXS_IMAGE_BAD); + } + + be_version = emlxs_be_version(buffer, len, &ufi_plus); + + /* Check if this is a standard BE3 image */ + if (be_version != 3) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid image provided."); + return (EMLXS_IMAGE_INCOMPATIBLE); + } + + ufi_hdr = (emlxs_be3_ufi_header_t *)buffer; + +#ifdef EMLXS_BIG_ENDIAN + /* Big Endian Swapping */ + /* Swap ufi header */ + ufi_hdr->ufi_version = + SWAP32(ufi_hdr->ufi_version); + ufi_hdr->file_length = + SWAP32(ufi_hdr->file_length); + ufi_hdr->checksum = + SWAP32(ufi_hdr->checksum); + ufi_hdr->antidote = + SWAP32(ufi_hdr->antidote); + ufi_hdr->image_cnt = + SWAP32(ufi_hdr->image_cnt); +#endif /* EMLXS_BIG_ENDIAN */ + + if (len != ufi_hdr->file_length) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Invalid image size (%d != %d)", + len, ufi_hdr->file_length); + + return (EMLXS_IMAGE_BAD); + } + + flash_image_hdr = NULL; + image_hdr = (emlxs_be3_image_header_t *)(buffer + + sizeof (emlxs_be3_ufi_header_t)); + for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) { +#ifdef EMLXS_BIG_ENDIAN + image_hdr->id = SWAP32(image_hdr->id); + image_hdr->offset = SWAP32(image_hdr->offset); + image_hdr->length = SWAP32(image_hdr->length); + image_hdr->checksum = SWAP32(image_hdr->checksum); +#endif /* EMLXS_BIG_ENDIAN */ + + if (image_hdr->id == UFI_BE3_FLASH_ID) { + flash_image_hdr = image_hdr; + } + } + + if (!flash_image_hdr) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "No flash image found."); + + return (EMLXS_IMAGE_BAD); + } + + /* Scan for flash dir signature */ + bptr = (uint8_t *)buffer + flash_image_hdr->offset; + flash_dir = NULL; + for (i = 0; i < flash_image_hdr->length; i++, bptr++) { + if (strncmp((char *)bptr, BE_DIR_SIGNATURE, + sizeof (BE_DIR_SIGNATURE)) == 0) { + flash_dir = (emlxs_be3_flash_dir_t *)bptr; + break; + } + } + + if (!flash_dir) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Unable to find flash directory."); + + return (EMLXS_IMAGE_BAD); + } + +#ifdef EMLXS_BIG_ENDIAN + /* Big Endian Swapping */ + /* Swap flash dir */ + flash_dir->header.format_rev = + SWAP32(flash_dir->header.format_rev); + flash_dir->header.checksum = + SWAP32(flash_dir->header.checksum); + flash_dir->header.antidote = + SWAP32(flash_dir->header.antidote); + flash_dir->header.entry_count = + SWAP32(flash_dir->header.entry_count); + flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0); + flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1); + flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2); + flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3); + + for (i = 0; i < BE_CONTROLLER_SIZE; i++) { + flash_dir->header.controller[i].vendor_id = + SWAP32(flash_dir->header.controller[i].vendor_id); + flash_dir->header.controller[i].device_id = + SWAP32(flash_dir->header.controller[i].device_id); + flash_dir->header.controller[i].sub_vendor_id = + SWAP32(flash_dir->header.controller[i].sub_vendor_id); + flash_dir->header.controller[i].sub_device_id = + SWAP32(flash_dir->header.controller[i].sub_device_id); + } + + for (i = 0; i < flash_dir->header.entry_count; i++) { + entry = &flash_dir->entry[i]; + + if ((entry->type == 0) || + (entry->type == (uint32_t)-1) || + (entry->image_size == 0)) { + continue; + } + + flash_dir->entry[i].type = + SWAP32(flash_dir->entry[i].type); + flash_dir->entry[i].offset = + SWAP32(flash_dir->entry[i].offset); + flash_dir->entry[i].block_size = + SWAP32(flash_dir->entry[i].block_size); + flash_dir->entry[i].image_size = + SWAP32(flash_dir->entry[i].image_size); + flash_dir->entry[i].checksum = + SWAP32(flash_dir->entry[i].checksum); + flash_dir->entry[i].entry_point = + SWAP32(flash_dir->entry[i].entry_point); + flash_dir->entry[i].resv0 = + SWAP32(flash_dir->entry[i].resv0); + flash_dir->entry[i].resv1 = + SWAP32(flash_dir->entry[i].resv1); + } +#endif /* EMLXS_BIG_ENDIAN */ + + /* Verify image checksum */ + if (flash_dir->header.checksum != flash_image_hdr->checksum) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Invalid flash directory checksum. (%x != %x)\n", + flash_dir->header.checksum, flash_image_hdr->checksum); + return (EMLXS_IMAGE_BAD); + } + + /* Verify adapter model */ + found = 0; + for (i = 0; i < BE_CONTROLLER_SIZE; i++) { + if (flash_dir->header.controller[i].device_id == + hba->model_info.device_id) { + found = 1; + } + } + + if (!found) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid adapter device id=0x%x.", + hba->model_info.device_id); + return (EMLXS_IMAGE_INCOMPATIBLE); + } + + /* Build fw_image table */ + fw_image->be_version = 3; + fw_image->ufi_plus = ufi_plus; + for (i = 0; i < flash_dir->header.entry_count; i++) { + entry = &flash_dir->entry[i]; + + if ((entry->type == 0) || + (entry->type == (uint32_t)-1) || + (entry->image_size == 0)) { + continue; + } + + switch (entry->type) { + case BE_FLASHTYPE_REDBOOT: + file = &fw_image->file[REDBOOT_FLASHTYPE]; + (void) strcpy(file->label, "REDBOOT"); + file->type = MGMT_FLASHROM_OPTYPE_REDBOOT; + break; + case BE_FLASHTYPE_ISCSI_BIOS: + file = &fw_image->file[ISCSI_BIOS_FLASHTYPE]; + (void) strcpy(file->label, "ISCSI BIOS"); + file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS; + break; + case BE_FLASHTYPE_PXE_BIOS: + file = &fw_image->file[PXE_BIOS_FLASHTYPE]; + (void) strcpy(file->label, "PXE BIOS"); + file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS; + break; + case BE_FLASHTYPE_FCOE_BIOS: + file = &fw_image->file[FCOE_BIOS_FLASHTYPE]; + (void) strcpy(file->label, "FCOE BIOS"); + file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS; + break; + case BE_FLASHTYPE_ISCSI_FIRMWARE: + file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE]; + (void) strcpy(file->label, "ISCSI FIRMWARE"); + file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE; + break; + case BE_FLASHTYPE_FCOE_FIRMWARE: + file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE]; + (void) strcpy(file->label, "FCOE FIRMWARE"); + file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE; + break; + case BE_FLASHTYPE_NCSI_FIRMWARE: + file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE]; + (void) strcpy(file->label, "NCSI FIRMWARE"); + file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE; + break; + case BE_FLASHTYPE_FLASH_ISM: + case BE_FLASHTYPE_FCOE_BACKUP: + case BE_FLASHTYPE_ISCSI_BACKUP: + continue; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "Unknown image type found. type=%x", + entry->type); + continue; + } + + file->be_version = fw_image->be_version; + file->ufi_plus = fw_image->ufi_plus; + file->image_size = entry->image_size; + + if (ufi_plus) { + file->image_offset = entry->offset; + file->block_size = entry->block_size; + file->block_crc = entry->checksum; + file->load_address = entry->entry_point; + } else { + file->image_offset = entry->offset + + flash_image_hdr->offset; + file->block_size = entry->block_size; + + wptr = (uint32_t *)(buffer + file->image_offset + + file->block_size); + + /* Read load address */ + value = *(wptr - 3); + file->load_address = BE_SWAP32(value); + + /* Read block_crc */ + value = *(wptr - 1); + file->block_crc = BE_SWAP32(value); + } + + /* Make sure image will fit in block specified */ + if (file->image_size + 12 > file->block_size) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, + "%s: Image too large for block. image=%x block=%x", + file->label, file->image_size, file->block_size); + + bzero(fw_image, sizeof (emlxs_be_fw_image_t)); + return (EMLXS_IMAGE_BAD); + } + + /* Automatically create a backup file entry for firmware */ + if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) { + file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE]; + + bcopy((uint8_t *)file, (uint8_t *)file2, + sizeof (emlxs_be_fw_file_t)); + file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP; + (void) strcpy(file2->label, "FCOE BACKUP"); + + /* Save FCOE version info */ + bptr = (uint8_t *)buffer + file->image_offset + 0x30; + (void) strncpy(fw_image->fcoe_label, (char *)bptr, + BE_VERSION_SIZE); + fw_image->fcoe_version = file->block_crc; + + } else if (file->type == + MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) { + file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE]; + + bcopy((uint8_t *)file, (uint8_t *)file2, + sizeof (emlxs_be_fw_file_t)); file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP; - file2->image_offset = file->image_offset; - file2->image_size = file->image_size; - file2->block_size = file->block_size; - file2->block_crc = file->block_crc; - file2->load_address = file->load_address; + (void) strcpy(file2->label, "ISCSI BACKUP"); + + /* Save ISCSI version info */ + bptr = (uint8_t *)buffer + file->image_offset + 0x30; + (void) strncpy(fw_image->iscsi_label, (char *)bptr, + BE_VERSION_SIZE); + fw_image->iscsi_version = file->block_crc; } } - if (fw_image->version == 0) { + if (fw_image->fcoe_version == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, "Unable to find FCOE firmware component."); @@ -1143,7 +1437,8 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, /* Display contents */ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "UFI Image: %08x, %s", fw_image->version, fw_image->label); + "BE3 UFI Image: %08x, %s", fw_image->fcoe_version, + fw_image->fcoe_label); for (i = 0; i < BE_MAX_FLASHTYPES; i++) { file = &fw_image->file[i]; @@ -1153,15 +1448,16 @@ emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, - "%s: type=%x block=%x image=%x offset=%x crc=%x load=%x", - file->label, file->type, file->block_size, - file->image_size, file->image_offset, file->block_crc, - file->load_address); + "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x " + "load=%x", + file->label, file->be_version, (file->ufi_plus)? "+":"", + file->type, file->block_size, file->image_size, + file->image_offset, file->block_crc, file->load_address); } return (0); -} /* emlxs_sli4_validate_image() */ +} /* emlxs_be3_validate_image() */ static int32_t @@ -1176,6 +1472,7 @@ emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, MATCHMAP *mp = NULL; emlxs_be_fw_image_t fw_image; emlxs_be_fw_file_t *file; + uint32_t be_version; /* For now we will not take the driver offline during a download */ offline = 0; @@ -1192,9 +1489,30 @@ emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, return (EMLXS_IMAGE_BAD); } - /* Validate image */ - if ((rval = emlxs_sli4_validate_image(hba, buffer, len, &fw_image))) { - return (rval); + be_version = emlxs_be_version(buffer, len, 0); + + switch (be_version) { + case 0: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid image provided. Non-UFI format."); + return (EMLXS_IMAGE_INCOMPATIBLE); + case 2: + rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image); + if (rval) { + return (rval); + } + break; + case 3: + rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image); + if (rval) { + return (rval); + } + break; + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, + "Invalid image provided. Unknown BE version. (%x)", + be_version); + return (EMLXS_IMAGE_INCOMPATIBLE); } /* Allocate resources */ @@ -1230,6 +1548,7 @@ emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, rval = emlxs_sli4_verify_crc(hba, file, mbq, mp); if (rval == 0) { + /* Do not update */ file->image_size = 0; continue; } @@ -1239,6 +1558,7 @@ emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, if (!update) { offline = 0; + rval = 0; goto done; } @@ -1274,11 +1594,11 @@ emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, done: if (mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } if (mp) { - (void) emlxs_mem_buf_free(hba, mp); + emlxs_mem_buf_free(hba, mp); } if (offline) { @@ -1292,7 +1612,8 @@ done: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg, "Please reboot system or power cycle adapter " - "to activate new firmware: %s", fw_image.label); + "to activate new firmware: %s", + fw_image.fcoe_label); } else { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, @@ -1679,7 +2000,6 @@ emlxs_start_abs_download(emlxs_hba_t *hba, return (rval); } - mb = (MAILBOX *)mbox; AbsChangeParams = emlxs_build_parms(Buffer, @@ -2598,6 +2918,9 @@ download: return (EMLXS_IMAGE_FAILED); } + /* Cleanup using old wakeup paramters */ + (void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms); + return (0); } /* emlxs_proc_rel_2mb() */ @@ -3192,6 +3515,7 @@ done: + static int emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms, @@ -4286,7 +4610,6 @@ emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer, rval = EMLXS_IMAGE_BAD; goto EXIT_ABS_DOWNLOAD; - } EraseByteCount = AifHdr->Area_Size; @@ -4758,6 +5081,7 @@ emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version) } /* emlxs_sbus_fcode_check() */ + static uint32_t emlxs_type_check(uint32_t type) { @@ -4774,7 +5098,6 @@ emlxs_type_check(uint32_t type) } /* emlxs_type_check() */ - extern int32_t emlxs_boot_code_disable(emlxs_hba_t *hba) { @@ -4784,7 +5107,8 @@ emlxs_boot_code_disable(emlxs_hba_t *hba) vpd = &VPD; - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { return (EMLXS_OP_NOT_SUP); } @@ -4840,7 +5164,8 @@ emlxs_boot_code_enable(emlxs_hba_t *hba) vpd = &VPD; - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { return (FC_SUCCESS); } @@ -4911,7 +5236,8 @@ emlxs_boot_code_state(emlxs_hba_t *hba) { emlxs_port_t *port = &PPORT; - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { return (FC_SUCCESS); } diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c index 63a4e97e1c..0810bdfe36 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -385,72 +385,6 @@ done: } /* emlxs_menlo_get_paniclog() */ -static uint32_t -emlxs_menlo_get_sfp( - emlxs_hba_t *hba, - menlo_rsp_t *rsp_buf, - uint32_t rsp_size) -{ - emlxs_port_t *port = &PPORT; - uint32_t cmd_size; - menlo_cmd_t *cmd_buf = NULL; - uint32_t rval = 0; - - if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) { - return (DFC_INVALID_ADAPTER); - } - - cmd_size = sizeof (menlo_get_cmd_t); - cmd_buf = (menlo_cmd_t *)kmem_zalloc(cmd_size, KM_SLEEP); - - cmd_buf->code = MENLO_CMD_GET_SFP_DATA; - cmd_buf->get.context = 0; - cmd_buf->get.length = rsp_size; - -#ifdef EMLXS_BIG_ENDIAN - emlxs_swap32_buffer((uint8_t *)cmd_buf, cmd_size); -#endif /* EMLXS_BIG_ENDIAN */ - - if (rval = emlxs_send_menlo_cmd(hba, (uint8_t *)cmd_buf, cmd_size, - (uint8_t *)rsp_buf, &rsp_size)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "emlxs_menlo_get_sfp: Unable to send command."); - goto done; - } -#ifdef EMLXS_BIG_ENDIAN - emlxs_swap32_buffer((uint8_t *)rsp_buf, rsp_size); -#endif /* EMLXS_BIG_ENDIAN */ - - if (rsp_buf->code != 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "emlxs_menlo_get_sfp: Menlo command error. code=%d.\n", - rsp_buf->code); - } - - rval = rsp_buf->code; - -done: - - if (cmd_buf) { - kmem_free(cmd_buf, sizeof (menlo_get_cmd_t)); - } - - return (rval); - -} /* emlxs_menlo_get_sfp() */ - - -static uint32_t -emlxs_isgraph( - uint8_t c) -{ - if ((c >= 33) && (c <= 126)) { - return (1); - } - - return (0); - -} /* emlxs_isgraph() */ extern void @@ -739,7 +673,8 @@ emlxs_get_dump( } if (size_cee) { - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { wptr[i++] = EMLXS_FAT_FILE_ID; } else { wptr[i++] = EMLXS_CEE_FILE_ID; @@ -1017,75 +952,6 @@ emlxs_dump_word_txtfile( } /* emlxs_dump_word_txtfile() */ -static uint32_t -emlxs_dump_byte_txtfile( - emlxs_file_t *fpTxtFile, - uint8_t *pBuffer, - uint32_t ByteCount, - char *pSidLegend, - char *pLidLegend) -{ - char buf1[1024]; - char buf2[1024]; - uint8_t *ptr; - uint32_t j, k, m, p, cnt; - - if (!fpTxtFile) { - return (1); - } - - /* Write Legend String to the TXT File */ - (void) emlxs_fprintf(fpTxtFile, "%s: %s\n", pSidLegend, pLidLegend); - - /* Write the buffer to the TXT File */ - - ptr = pBuffer; - k = ByteCount; - - for (j = 0; j < k; j++) { /* for all bytes in the buffer */ - buf1[0] = 0; - buf2[0] = 0; - - if ((j & 0x0F) == 0) { - (void) sprintf(buf1, "\n%04x:", j); - (void) strcat(buf2, buf1); - cnt = 0; /* count characters on the new line */ - } - (void) sprintf(buf1, " %02x", ptr[j]); /* print 1 byte */ - (void) strcat(buf2, buf1); - cnt++; /* count 1 byte */ - if ((cnt == 16) || (j == k - 1)) { - (void) sprintf(buf1, " "); - (void) strcat(buf2, buf1); - if (j == k - 1) { - for (p = 0; p < 16 - cnt; p++) { - (void) sprintf(buf1, " "); - (void) strcat(buf2, buf1); - } - } - for (m = 0; m < cnt; m++) { - if (emlxs_isgraph(ptr[j - cnt + 1 + m])) { - (void) sprintf(buf1, "%c", - ptr[j - cnt + 1 + m]); - (void) strcat(buf2, buf1); - } else { - (void) sprintf(buf1, "."); - (void) strcat(buf2, buf1); - } - } - } - /* end if */ - (void) emlxs_fwrite((uint8_t *)buf2, strlen(buf2), 1, - fpTxtFile); - - } /* end for */ - - emlxs_fputc('\n', fpTxtFile); - emlxs_fputc('\n', fpTxtFile); - emlxs_fflush(fpTxtFile); - return (0); - -} /* emlxs_dump_byte_txtfile() */ static uint32_t @@ -2342,7 +2208,8 @@ emlxs_dump_file_create( *fpCeeFile = NULL; if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) || - (hba->model_info.chip == EMLXS_BE_CHIP)) { + (hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { if ((*fpCeeFile = emlxs_fopen(hba, EMLXS_CEE_FILE)) == NULL) { emlxs_fdelete(*fpTxtFile); @@ -3024,7 +2891,7 @@ emlxs_dump_drv_region( status = emlxs_get_dump_region(hba, regionId, *pBuf, &size); if (status != 0) { - kmem_free(pBuf, size); + kmem_free(*pBuf, size); *pBuf = NULL; return (1); @@ -3755,7 +3622,7 @@ emlxs_dump_saturn_log( "Unable to read event log. status=%x", mb->mbxStatus); - (void) emlxs_mem_buf_free(hba, mp); + emlxs_mem_buf_free(hba, mp); kmem_free(mbq, sizeof (MAILBOXQ)); return (1); } @@ -3788,7 +3655,7 @@ emlxs_dump_saturn_log( } #endif /* FMA_SUPPORT */ - (void) emlxs_mem_buf_free(hba, mp); + emlxs_mem_buf_free(hba, mp); kmem_free(mbq, sizeof (MAILBOXQ)); return (status); @@ -3816,7 +3683,8 @@ emlxs_dump_tigershark_log( IOCTL_COMMON_MANAGE_FAT *fat; mbox_req_hdr_t *hdr_req; - if (hba->model_info.chip != EMLXS_BE_CHIP) { + if ((hba->model_info.chip != EMLXS_BE2_CHIP) && + (hba->model_info.chip != EMLXS_BE3_CHIP)) { return (1); } @@ -3839,7 +3707,7 @@ emlxs_dump_tigershark_log( /* Query FAT */ mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -3873,17 +3741,19 @@ emlxs_dump_tigershark_log( EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, "FAT: log_size=%d", log_size); - if (log_size) { - if ((buffer = (uint8_t *)kmem_alloc( - buffer_size, KM_NOSLEEP)) == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, - "Unable to allocate log buffer."); + if (buffer_size == 0) { + goto done; + } - rval = 1; - goto done; - } - bzero(buffer, buffer_size); + if ((buffer = (uint8_t *)kmem_alloc( + buffer_size, KM_NOSLEEP)) == NULL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_dump_msg, + "Unable to allocate log buffer."); + + rval = 1; + goto done; } + bzero(buffer, buffer_size); /* Upload Log */ bptr = buffer; @@ -3899,7 +3769,7 @@ emlxs_dump_tigershark_log( xfer_size = min(BE_MAX_XFER_SIZE, log_size); mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; mb->mbxCommand = MBX_SLI_CONFIG; @@ -3962,11 +3832,11 @@ emlxs_dump_tigershark_log( done: if (mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } if (mp) { - (void) emlxs_mem_buf_free(hba, mp); + emlxs_mem_buf_free(hba, mp); } if (buffer) { @@ -4015,7 +3885,8 @@ emlxs_dump_user_event( (void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile); } - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { (void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile); } @@ -4155,7 +4026,8 @@ emlxs_dump_drv_event( (void) emlxs_dump_saturn_log(hba, fpTxtFile, fpDmpFile); } - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { (void) emlxs_dump_tigershark_log(hba, fpTxtFile, fpCeeFile); } diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c index ce4d78ab7b..433d987a57 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2011 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +31,7 @@ EMLXS_MSG_DEF(EMLXS_ELS_C); static void emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp); -static void emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp); +static void emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp); static void emlxs_handle_sol_plogi(emlxs_port_t *port, emlxs_buf_t *sbp); static void emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp); static void emlxs_handle_sol_logo(emlxs_port_t *port, emlxs_buf_t *sbp); @@ -55,12 +55,21 @@ static void emlxs_handle_unsol_auth(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); static void emlxs_handle_unsol_gen_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); +static void emlxs_handle_unsol_echo_cmd(emlxs_port_t *port, CHANNEL *cp, + IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); +static void emlxs_handle_unsol_rtv_cmd(emlxs_port_t *port, CHANNEL *cp, + IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); +static void emlxs_handle_unsol_rls_cmd(emlxs_port_t *port, CHANNEL *cp, + IOCBQ *iocbq, MATCHMAP *mp, uint32_t size); static void emlxs_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq, uint32_t flag); static void emlxs_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp, IOCBQ *iocbq, uint32_t flag); + +#if (EMLXS_MODREV < EMLXS_MODREV4) static void emlxs_send_rsnn(emlxs_port_t *port); +#endif /* < EMLXS_MODREV4 */ @@ -182,7 +191,7 @@ emlxs_els_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) switch (command) { case ELS_CMD_FDISC: /* Fabric login */ - emlxs_handle_sol_fdisk(port, sbp); + emlxs_handle_sol_fdisc(port, sbp); break; @@ -319,6 +328,11 @@ emlxs_els_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) #endif /* DHCHAP_SUPPORT */ } + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_vpi_logi_failed_notify( + sbp->port); + } + break; default: @@ -327,10 +341,8 @@ emlxs_els_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) emlxs_pkt_complete(sbp, iocb->ULPSTATUS, iocb->un.grsp.perr.statLocalError, 1); - } - break; default: @@ -357,9 +369,11 @@ emlxs_els_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, { emlxs_hba_t *hba = HBA; uint32_t cmd_code; + IOCB *iocb; HBASTATS.ElsCmdReceived++; + iocb = &iocbq->iocb; cmd_code = *((uint32_t *)mp->virt) & ELS_CMD_MASK; if (!(port->flag & EMLXS_PORT_BOUND)) { @@ -415,6 +429,74 @@ emlxs_els_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, emlxs_handle_unsol_auth(port, cp, iocbq, mp, size); break; + case ELS_CMD_TEST: + HBASTATS.ElsTestReceived++; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "%s: sid=%x. Dropping.", + emlxs_elscmd_xlate(cmd_code), + iocbq->iocb.un.elsreq.remoteID); + + /* drop it */ + emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT); + break; + + case ELS_CMD_ESTC: + HBASTATS.ElsEstcReceived++; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "%s: sid=%x. Dropping.", + emlxs_elscmd_xlate(cmd_code), + iocbq->iocb.un.elsreq.remoteID); + + /* drop it */ + emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT); + break; + + case ELS_CMD_FARPR: + HBASTATS.ElsFarprReceived++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "%s: sid=%x. Dropping.", + emlxs_elscmd_xlate(cmd_code), + iocbq->iocb.un.elsreq.remoteID); + + /* drop it */ + emlxs_close_els_exchange(hba, port, iocb->ULPCONTEXT); + break; + + case ELS_CMD_ECHO: + HBASTATS.ElsEchoReceived++; + emlxs_handle_unsol_echo_cmd(port, cp, iocbq, mp, size); + break; + + case ELS_CMD_RLS: + HBASTATS.ElsRlsReceived++; + emlxs_handle_unsol_rls_cmd(port, cp, iocbq, mp, size); + break; + + case ELS_CMD_RTV: + HBASTATS.ElsRtvReceived++; + emlxs_handle_unsol_rtv_cmd(port, cp, iocbq, mp, size); + break; + + case ELS_CMD_ABTX: + case ELS_CMD_RCS: + case ELS_CMD_RES: + case ELS_CMD_RSS: + case ELS_CMD_RSI: + case ELS_CMD_ESTS: + case ELS_CMD_RRQ: + case ELS_CMD_REC: + HBASTATS.ElsGenReceived++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "%s: sid=%x. Rejecting.", + emlxs_elscmd_xlate(cmd_code), + iocbq->iocb.un.elsreq.remoteID); + + (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, cmd_code, + LSRJT_CMD_UNSUPPORTED, LSEXP_NOTHING_MORE); + break; + default: HBASTATS.ElsGenReceived++; emlxs_handle_unsol_gen_cmd(port, cp, iocbq, mp, size); @@ -441,6 +523,7 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) char buffer[64]; uint32_t i; int rc; + uint16_t altBbCredit; pkt = PRIV2PKT(sbp); sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t)); @@ -448,14 +531,16 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) iocbq = &sbp->iocbq; iocb = &iocbq->iocb; - if (sp->cmn.fPort) { - mutex_enter(&EMLXS_PORT_LOCK); + mutex_enter(&EMLXS_PORT_LOCK); + /* Save the fabric service parameters and did */ + port->did = iocb->un.elsreq.myID; + bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM)); + + if (sp->cmn.fPort) { hba->flag |= FC_FABRIC_ATTACHED; hba->flag &= ~FC_PT_TO_PT; - /* Save our new port ID */ - port->did = iocb->un.elsreq.myID; pkt->pkt_resp_fhdr.s_id = LE_SWAP24_LO(FABRIC_DID); pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did); @@ -471,24 +556,23 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) hba->fc_ratov = (LE_SWAP32(sp->cmn.w2.r_a_tov) + 999) / 1000; - if (hba->topology != TOPOLOGY_LOOP) { - /* - * If we are a N-port connected to a Fabric, - * fixup sparam's so logins to devices on remote - * loops work. - */ - hba->sparam.cmn.altBbCredit = 1; - - /* Set this bit in all the port sparam copies */ - for (i = 0; i < MAX_VPORTS; i++) { - vport = &VPORT(i); + /* + * If we are a N-port connected to a Fabric, + * fixup sparam's so logins to devices on remote + * loops work. + */ + altBbCredit = (hba->topology != TOPOLOGY_LOOP)? 1:0; + hba->sparam.cmn.altBbCredit = altBbCredit; - if (!(vport->flag & EMLXS_PORT_BOUND)) { - continue; - } + /* Set this bit in all the port sparam copies */ + for (i = 0; i < MAX_VPORTS; i++) { + vport = &VPORT(i); - vport->sparam.cmn.altBbCredit = 1; + if (!(vport->flag & EMLXS_PORT_BOUND)) { + continue; } + + vport->sparam.cmn.altBbCredit = altBbCredit; } if (sp->cmn.rspMultipleNPort) { @@ -534,123 +618,25 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, "FLOGI: did=%x sid=%x %s", did, port->did, buffer); - /* Update our service parms */ + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + /* Deferred completion */ + (void) emlxs_vpi_logi_cmpl_notify(sbp->port, sbp); + return; + } + if (!(mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1); return; - } - /* For SLI4 we replace CONFIG_LINK and REG_LOGIN of */ - /* Fabric with a REG_VFI mailbox command. */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - emlxs_port_t *vpip = sbp->port; - VFIobj_t *vfip; - FCFIobj_t *fcfp; - uint32_t regvfi; - - vfip = vpip->VFIp; - fcfp = vfip->FCFIp; - regvfi = vfip->state & RESOURCE_VFI_REG; - - /* Save the FCF service parameters */ - bcopy((void *)sp, (void *)&fcfp->fcf_sparam, - sizeof (SERV_PARM)); - - if (emlxs_mb_check_sparm(hba, sp)) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_node_create_failed_msg, - "Invalid Fabric parameters. did=%06x", - port->did); - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); - emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, - IOERR_NO_RESOURCES, 1); - return; - } - - if (!regvfi) { - if (emlxs_mb_reg_vfi(hba, mbox, vfip, vpip) == - 0) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_sli_detail_msg, - "Cannot REG_VFI for FCF: sid=%x", - port->did); - - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); - emlxs_pkt_complete(sbp, - IOSTAT_LOCAL_REJECT, - IOERR_NO_RESOURCES, 1); - return; - } - mbox->sbp = (uint8_t *)sbp; - - rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, - MBX_NOWAIT, 0); - if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_sli_detail_msg, - "Cannot REG_VFI for FCF: sid=%x", - port->did); - - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); - emlxs_pkt_complete(sbp, - IOSTAT_LOCAL_REJECT, - IOERR_NO_RESOURCES, 1); - return; - } - /* Preset the state for the REG_VFI cmpl */ - emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1); - - /* Deferred completion of this pkt until */ - /* REG_VFI is complete */ - return; - } - /* VFI is already Registered */ - - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); - emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); - - EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); - if (regvfi) { - /* - * If NPIV Fabric support has just been - * established on the physical port, then - * notify the vports of the link up. - */ - if ((hba->flag & FC_NPIV_ENABLED) && - (hba->flag & FC_NPIV_SUPPORTED)) { - /* Skip the physical port */ - for (i = 1; i < MAX_VPORTS; i++) { - vport = &VPORT(i); - - if (!(vport->flag & - EMLXS_PORT_BOUND) || - !(vport->flag & - EMLXS_PORT_ENABLE)) { - continue; - } - - emlxs_port_online(vport); - } - } - } - return; - } - - /* Save the fabric service parameters */ - bcopy((void *)sp, (void *)&port->fabric_sparam, - sizeof (SERV_PARM)); - + /* Update our service parms */ emlxs_mb_config_link(hba, mbox); rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } /* Preset the state for the reg_did */ @@ -668,8 +654,6 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) } else { /* No switch */ - mutex_enter(&EMLXS_PORT_LOCK); - hba->flag &= ~FC_FABRIC_ATTACHED; hba->flag |= FC_PT_TO_PT; @@ -707,7 +691,7 @@ emlxs_handle_sol_flogi(emlxs_port_t *port, emlxs_buf_t *sbp) static void -emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp) +emlxs_handle_sol_fdisc(emlxs_port_t *port, emlxs_buf_t *sbp) { emlxs_hba_t *hba = HBA; emlxs_config_t *cfg = &CFG; @@ -728,13 +712,12 @@ emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp) mutex_enter(&EMLXS_PORT_LOCK); - /* Save our new port ID */ + /* Save the fabric service parameters and did */ port->did = iocb->un.elsreq.myID; - pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did); - - /* Save the fabric service parameters */ bcopy((void *)sp, (void *)&port->fabric_sparam, sizeof (SERV_PARM)); + pkt->pkt_resp_fhdr.d_id = LE_SWAP24_LO(port->did); + mutex_exit(&EMLXS_PORT_LOCK); buffer[0] = 0; @@ -750,34 +733,10 @@ emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp) #endif /* DHCHAP_SUPPORT */ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg, - "FDISK: did=%x sid=%x %s", did, port->did, buffer); + "FDISC: did=%x sid=%x %s", did, port->did, buffer); if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - emlxs_port_t *pport = &PPORT; - - port->VFIp = pport->VFIp; - - if (emlxs_mb_check_sparm(hba, sp)) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_node_create_failed_msg, - "Invalid Fabric parameters. did=%06x", - port->did); - emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, - IOERR_NO_RESOURCES, 1); - return; - } - - /* Preset the state for the REG_VFI cmpl */ - emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1); - - if (port->flag & EMLXS_PORT_REG_VPI_CMPL) { - emlxs_pkt_complete(sbp, -1, 0, 1); - } else { - /* Deferred completion of this pkt until */ - /* REG_VPI is complete */ - (void) emlxs_mb_reg_vpi(port, sbp); - } - + (void) emlxs_vpi_logi_cmpl_notify(sbp->port, sbp); return; } @@ -788,7 +747,7 @@ emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp) rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } } @@ -808,7 +767,7 @@ emlxs_handle_sol_fdisk(emlxs_port_t *port, emlxs_buf_t *sbp) return; -} /* emlxs_handle_sol_fdisk() */ +} /* emlxs_handle_sol_fdisc() */ static void @@ -879,7 +838,6 @@ emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp) fc_packet_t *pkt; uint32_t did; NODELIST *ndlp; - RPIobj_t *rp; pkt = PRIV2PKT(sbp); did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); @@ -895,11 +853,11 @@ emlxs_handle_sol_adisc(emlxs_port_t *port, emlxs_buf_t *sbp) emlxs_node_open(port, ndlp, hba->channel_ip); if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi); - if (rp && (rp->state & RESOURCE_RPI_PAUSED)) { - (void) emlxs_mb_resume_rpi(hba, sbp, - ndlp->nlp_Rpi); - rp->state &= ~RESOURCE_RPI_PAUSED; + + emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1); + + if (emlxs_rpi_resume_notify(port, + ndlp->rpip, sbp) == 0) { /* * Delay ADISC cmpl to ULP till * after RESUME_RPI @@ -937,6 +895,13 @@ emlxs_handle_sol_prli(emlxs_port_t *port, emlxs_buf_t *sbp) /* Check for FCP support */ if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && (npr->prliType == PRLI_FCP_TYPE)) { + /* Clear FCP2 support if no ADISC support requested */ + if (cfg[CFG_ADISC_SUPPORT].current == 0) { + npr->ConfmComplAllowed = 0; + npr->TaskRetryIdReq = 0; + npr->Retry = 0; + } + /* Check for target */ if (npr->targetFunc) { ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE; @@ -1316,12 +1281,11 @@ emlxs_process_unsol_plogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp, ELS_CMD_PLOGI, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); - /* - * We still need to do reg_did and unreg_did - * to free up rpi - */ - (void) emlxs_mb_reg_did(port, sid, sp, NULL, NULL, - (IOCBQ *)1); + /* Clear temporary RPI in firmware */ + if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { + (void) emlxs_mb_reg_did(port, sid, sp, + NULL, NULL, (IOCBQ *)1); + } return (1); } @@ -1377,8 +1341,7 @@ emlxs_process_unsol_plogi(emlxs_port_t *port, IOCBQ *iocbq, MATCHMAP *mp, rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } } @@ -1490,6 +1453,7 @@ emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, PRLI *npr; fc_unsol_buf_t *ubp; emlxs_ub_priv_t *ub_priv; + uint32_t task_retry_id; iocb = &iocbq->iocb; sid = iocb->un.elsreq.remoteID; @@ -1511,6 +1475,13 @@ emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, /* Check for FCP2 support */ if ((npr->prliType == PRLI_FCP_TYPE) && npr->targetFunc) { + /* Clear FCP2 support if no ADISC support is requested */ + if (cfg[CFG_ADISC_SUPPORT].current == 0) { + npr->ConfmComplAllowed = 0; + npr->TaskRetryIdReq = 0; + npr->Retry = 0; + } + /* Check for target */ if (npr->targetFunc) { ndlp->nlp_fcp_info |= NLP_FCP_TGT_DEVICE; @@ -1525,8 +1496,17 @@ emlxs_handle_unsol_prli(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, ndlp->nlp_fcp_info &= ~NLP_FCP_INI_DEVICE; } + /* If TRI support is not required then force */ + /* the task_retry_id value to one */ + if (cfg[CFG_TRI_REQUIRED].current == 0) { + task_retry_id = 1; + } else { + task_retry_id = npr->TaskRetryIdReq; + } + /* Check for FCP2 target support */ - if (npr->targetFunc && npr->Retry) { + /* Retry and TaskRetryId bits are both required here */ + if (npr->targetFunc && npr->Retry && task_retry_id) { ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; } else { ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; @@ -1942,15 +1922,17 @@ emlxs_handle_unsol_logo(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, emlxs_swap_els_ub(ubp); #endif /* EMLXS_MODREV2X */ - /* Clear the RPI */ + /* Unregister the node */ if ((sid & FABRIC_DID_MASK) == FABRIC_DID_MASK) { - if (emlxs_mb_unreg_did(port, sid, NULL, ubp, NULL) == 0) { - /* - * Deferred completion of this ubp - * until unreg login is complete - */ - - return; + if (ndlp) { + if (emlxs_mb_unreg_node(port, ndlp, NULL, + ubp, NULL) == 0) { + /* + * Deferred completion of this ubp + * until unreg login is complete + */ + return; + } } } @@ -2027,6 +2009,303 @@ drop_it: } /* emlxs_handle_unsol_gen_cmd() */ +/* ARGSUSED */ +static void +emlxs_handle_unsol_echo_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, + MATCHMAP *mp, uint32_t size) +{ + emlxs_hba_t *hba = HBA; + uint8_t *bp; + IOCB *iocb; + uint32_t *lp; + uint32_t sid; + fc_packet_t *pkt; + uint32_t cmd; + + iocb = &iocbq->iocb; + sid = iocb->un.elsreq.remoteID; + + bp = mp->virt; + lp = (uint32_t *)bp; + cmd = *lp & ELS_CMD_MASK; + + if (!(pkt = emlxs_pkt_alloc(port, + size, 0, 0, KM_NOSLEEP))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "ECHO: sid=%x. Unable to allocate pkt. Rejecting.", + sid); + + (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, + ELS_CMD_ECHO, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); + return; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "ECHO: sid=%x. Accepting.", + sid); + + /* Common initialization */ + pkt->pkt_tran_type = FC_PKT_OUTBOUND; + pkt->pkt_timeout = (2 * hba->fc_ratov); + + if ((uint32_t)iocb->ULPCLASS == CLASS2) { + pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; + pkt->pkt_tran_flags |= FC_TRAN_CLASS2; + } + + /* Build the fc header */ + pkt->pkt_cmd_fhdr.d_id = + LE_SWAP24_LO(iocb->un.elsreq.remoteID); + pkt->pkt_cmd_fhdr.r_ctl = + R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; + pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID); + pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; + pkt->pkt_cmd_fhdr.f_ctl = + F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; + pkt->pkt_cmd_fhdr.seq_id = 0; + pkt->pkt_cmd_fhdr.df_ctl = 0; + pkt->pkt_cmd_fhdr.seq_cnt = 0; + pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff; + pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT; + pkt->pkt_cmd_fhdr.ro = 0; + + /* Build the response */ + *lp = ELS_CMD_ACC; + bcopy(lp, pkt->pkt_cmd, size); + + if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { + /* Free the pkt */ + emlxs_pkt_free(pkt); + emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT); + } + + return; + +} /* emlxs_handle_unsol_echo_cmd() */ + + +/* ARGSUSED */ +static void +emlxs_handle_unsol_rtv_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, + MATCHMAP *mp, uint32_t size) +{ + emlxs_hba_t *hba = HBA; + uint8_t *bp; + IOCB *iocb; + uint32_t *lp; + uint32_t sid; + fc_packet_t *pkt; + uint32_t cmd; + SERV_PARM *sp; + + iocb = &iocbq->iocb; + sid = iocb->un.elsreq.remoteID; + + bp = mp->virt; + lp = (uint32_t *)bp; + cmd = *lp & ELS_CMD_MASK; + + if (!(pkt = emlxs_pkt_alloc(port, + (4 * sizeof (uint32_t)), 0, 0, KM_NOSLEEP))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "RTV: sid=%x. Unable to allocate pkt. Rejecting.", + sid); + + (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, + ELS_CMD_RTV, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); + return; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "RTV: sid=%x. Accepting.", + emlxs_elscmd_xlate(cmd), + sid); + + /* Common initialization */ + pkt->pkt_tran_type = FC_PKT_OUTBOUND; + pkt->pkt_timeout = (2 * hba->fc_ratov); + + if ((uint32_t)iocb->ULPCLASS == CLASS2) { + pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; + pkt->pkt_tran_flags |= FC_TRAN_CLASS2; + } + + /* Build the fc header */ + pkt->pkt_cmd_fhdr.d_id = + LE_SWAP24_LO(iocb->un.elsreq.remoteID); + pkt->pkt_cmd_fhdr.r_ctl = + R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; + pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID); + pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; + pkt->pkt_cmd_fhdr.f_ctl = + F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; + pkt->pkt_cmd_fhdr.seq_id = 0; + pkt->pkt_cmd_fhdr.df_ctl = 0; + pkt->pkt_cmd_fhdr.seq_cnt = 0; + pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff; + pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT; + pkt->pkt_cmd_fhdr.ro = 0; + + /* Build the response */ + sp = (SERV_PARM *)&port->sparam; + lp = (uint32_t *)pkt->pkt_cmd; + lp[0] = ELS_CMD_ACC; + lp[1] = LE_SWAP32(sp->cmn.w2.r_a_tov); + lp[2] = LE_SWAP32(sp->cmn.e_d_tov); + lp[3] = LE_SWAP32(sp->cmn.edtovResolution << 26); + + if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { + /* Free the pkt */ + emlxs_pkt_free(pkt); + emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT); + } + + return; + +} /* emlxs_handle_unsol_rtv_cmd() */ + + +/* ARGSUSED */ +static void +emlxs_rls_rsp_thread(emlxs_hba_t *hba, void *arg1, void *arg2) +{ + emlxs_port_t *port = (emlxs_port_t *)arg1; + fc_packet_t *pkt = (fc_packet_t *)arg2; + MAILBOXQ *mbq = NULL; + MAILBOX *mb; + la_els_rls_acc_t *rls; + uint32_t rval; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "RLS: sid=%x. Accepting.", + LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id)); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + goto dropit; + } + mb = (MAILBOX *)mbq; + + /* Read current link status */ + emlxs_mb_read_lnk_stat(hba, mbq); + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0); + + if (rval != MBX_SUCCESS) { + goto dropit; + } + + /* Build the response */ + rls = (la_els_rls_acc_t *)pkt->pkt_cmd; + rls->ls_code.ls_code = 0x02; + rls->rls_link_params.rls_link_fail = + mb->un.varRdLnk.linkFailureCnt; + rls->rls_link_params.rls_sync_loss = + mb->un.varRdLnk.lossSyncCnt; + rls->rls_link_params.rls_sig_loss = + mb->un.varRdLnk.lossSignalCnt; + rls->rls_link_params.rls_prim_seq_err = + mb->un.varRdLnk.primSeqErrCnt; + rls->rls_link_params.rls_invalid_word = + mb->un.varRdLnk.invalidXmitWord; + rls->rls_link_params.rls_invalid_crc = + mb->un.varRdLnk.crcCnt; + + LE_SWAP32_BUFFER((uint8_t *)rls, sizeof (la_els_rls_acc_t)); + + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + mbq = NULL; + + if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) { + goto dropit; + } + + return; + +dropit: + + emlxs_abort_els_exchange(hba, port, pkt->pkt_cmd_fhdr.rx_id); + + emlxs_pkt_free(pkt); + + if (mbq) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + } + + return; + +} /* emlxs_rls_rsp_thread() */ + + +/* ARGSUSED */ +static void +emlxs_handle_unsol_rls_cmd(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, + MATCHMAP *mp, uint32_t size) +{ + emlxs_hba_t *hba = HBA; + uint8_t *bp; + IOCB *iocb; + uint32_t *lp; + uint32_t sid; + fc_packet_t *pkt; + uint32_t cmd; + + iocb = &iocbq->iocb; + sid = iocb->un.elsreq.remoteID; + + bp = mp->virt; + lp = (uint32_t *)bp; + cmd = *lp++ & ELS_CMD_MASK; + + if (!(pkt = emlxs_pkt_alloc(port, + sizeof (la_els_rls_acc_t), 0, 0, KM_NOSLEEP))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "RLS: sid=%x. Unable to allocate pkt. Rejecting.", + sid); + + (void) emlxs_els_reply(port, iocbq, ELS_CMD_LS_RJT, + ELS_CMD_RLS, LSRJT_UNABLE_TPC, LSEXP_NOTHING_MORE); + return; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "RLS: sid=%x. Scheduling response.", + sid); + + /* Common initialization */ + pkt->pkt_tran_type = FC_PKT_OUTBOUND; + pkt->pkt_timeout = (2 * hba->fc_ratov); + + if ((uint32_t)iocb->ULPCLASS == CLASS2) { + pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; + pkt->pkt_tran_flags |= FC_TRAN_CLASS2; + } + + /* Build the fc header */ + pkt->pkt_cmd_fhdr.d_id = + LE_SWAP24_LO(iocb->un.elsreq.remoteID); + pkt->pkt_cmd_fhdr.r_ctl = + R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; + pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(iocb->un.elsreq.myID); + pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; + pkt->pkt_cmd_fhdr.f_ctl = + F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; + pkt->pkt_cmd_fhdr.seq_id = 0; + pkt->pkt_cmd_fhdr.df_ctl = 0; + pkt->pkt_cmd_fhdr.seq_cnt = 0; + pkt->pkt_cmd_fhdr.ox_id = (cmd >> ELS_CMD_SHIFT) & 0xff; + pkt->pkt_cmd_fhdr.rx_id = iocb->ULPCONTEXT; + pkt->pkt_cmd_fhdr.ro = 0; + + /* We must spawn a separate thread to send the */ + /* read link status mailbox command becasue we are */ + /* normally in a hardware interrupt context here. */ + emlxs_thread_spawn(hba, emlxs_rls_rsp_thread, + (void *)port, (void *)pkt); + + return; + +} /* emlxs_handle_unsol_rls_cmd() */ + + /* This handles the reply completions to unsolicited cmds */ /* ARGSUSED */ static void @@ -2155,7 +2434,6 @@ emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, emlxs_config_t *cfg = &CFG; fc_packet_t *pkt; ELS_PKT *els; - uint32_t rval; IOCB *iocb; iocb = &iocbq->iocb; @@ -2166,44 +2444,37 @@ emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, /* Allocate the pkt */ switch (type2) { case ELS_CMD_FLOGI: - if (!(pkt = emlxs_pkt_alloc(port, + pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (SERV_PARM), 0, - 0, KM_NOSLEEP))) { - return (1); - } + 0, KM_NOSLEEP); break; case ELS_CMD_ADISC: - if (!(pkt = emlxs_pkt_alloc(port, + pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (ADISC), 0, 0, - KM_NOSLEEP))) { - return (1); - } + KM_NOSLEEP); break; case ELS_CMD_PRLI: - if (!(pkt = emlxs_pkt_alloc(port, + pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (PRLI), 0, 0, - KM_NOSLEEP))) { - return (1); - } + KM_NOSLEEP); break; case ELS_CMD_PRLO: - if (!(pkt = emlxs_pkt_alloc(port, + pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (PRLO), 0, 0, - KM_NOSLEEP))) { - return (1); - } + KM_NOSLEEP); break; case ELS_CMD_AUTH: default: + pkt = emlxs_pkt_alloc(port, sizeof (uint32_t), + 0, 0, KM_NOSLEEP); + } - if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t), - 0, 0, KM_NOSLEEP))) { - return (1); - } + if (!pkt) { + goto dropit; } /* Common initialization */ @@ -2275,7 +2546,8 @@ emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, els->un.prli.readXferRdyDis = 1; - if (hba->vpd.feaLevelHigh >= 0x02) { + if ((hba->vpd.feaLevelHigh >= 0x02) && + (cfg[CFG_ADISC_SUPPORT].current != 0)) { els->un.prli.ConfmComplAllowed = 1; els->un.prli.Retry = 1; els->un.prli.TaskRetryIdReq = 1; @@ -2306,7 +2578,7 @@ emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) { - return (1); + goto dropit; } pkt->pkt_tran_type = FC_PKT_OUTBOUND; @@ -2350,12 +2622,18 @@ emlxs_els_reply(emlxs_port_t *port, IOCBQ *iocbq, uint32_t type, break; } - if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) { + if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) { /* Free the pkt */ emlxs_pkt_free(pkt); + goto dropit; } - return (rval); + return (0); + +dropit: + + emlxs_abort_els_exchange(hba, port, iocb->ULPCONTEXT); + return (1); } /* emlxs_els_reply() */ @@ -2952,6 +3230,7 @@ emlxs_ct_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, } /* emlxs_ct_handle_unsol_req() */ +#if (EMLXS_MODREV < EMLXS_MODREV4) static void emlxs_send_rsnn(emlxs_port_t *port) { @@ -3010,6 +3289,8 @@ emlxs_send_rsnn(emlxs_port_t *port) return; } /* emlxs_send_rsnn() */ +#endif /* < EMLXS_MODREV4 */ + extern uint32_t diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_event.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_event.c index b65bb6f092..2a03d28eb1 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_event.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_event.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -66,12 +66,6 @@ emlxs_event_queue_create(emlxs_hba_t *hba) { emlxs_event_queue_t *eventq = &EVENTQ; char buf[40]; -#ifdef MSI_SUPPORT - ddi_intr_handle_t handle; - uint32_t intr_pri; - int32_t actual; - uint32_t ret; -#endif /* MSI_SUPPORT */ ddi_iblock_cookie_t iblock; /* Clear the queue */ @@ -94,42 +88,9 @@ emlxs_event_queue_create(emlxs_hba_t *hba) } #ifdef MSI_SUPPORT else { - /* Allocate a temporary interrupt handle */ - actual = 0; - ret = - ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED, - EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL); - - if (ret != DDI_SUCCESS || actual == 0) { - cmn_err(CE_WARN, - "?%s%d: Unable to allocate temporary interrupt " - "handle. ret=%d actual=%d", DRIVER_NAME, - hba->ddiinst, ret, actual); - - bzero(eventq, sizeof (emlxs_event_queue_t)); - - return (0); - } - - /* Get the current interrupt priority */ - ret = ddi_intr_get_pri(handle, &intr_pri); - - if (ret != DDI_SUCCESS) { - cmn_err(CE_WARN, - "?%s%d: Unable to get interrupt priority. ret=%d", - DRIVER_NAME, hba->ddiinst, ret); - - bzero(eventq, sizeof (emlxs_event_queue_t)); - - return (0); - } - - /* Create the log mutex lock */ + /* Create event mutex lock */ mutex_init(&eventq->lock, buf, MUTEX_DRIVER, - (void *)((unsigned long)intr_pri)); - - /* Free the temporary handle */ - (void) ddi_intr_free(handle); + DDI_INTR_PRI(hba->intr_arg)); } #endif diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcf.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcf.c new file mode 100644 index 0000000000..ebe042a0fe --- /dev/null +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcf.c @@ -0,0 +1,12960 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2010 Emulex. All rights reserved. + * Use is subject to license terms. + */ + + +#include <emlxs.h> + +/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ +EMLXS_MSG_DEF(EMLXS_FCF_C); + +/* + * STATE MACHINE RULES: + * + * - State change requests to an XXXX object when operating within + * an emlxs_XXXX state management function must be made + * using the emlxs_XXXX_state() call. + * + * - State change requests to an XXXX object when operating outside + * an emlxs_XXXX state management function must be made + * using the emlxs_XXXX_alloc(), emlxs_XXXX_free(), emlxs_XXXX_event() + * or emlxs_XXXX_..._notify() calls. + * + * - emlxs_XXXX_..._notify() calls are used by routines outside + * this fcf module to enter the state machine. + * + * - It is forbidden to make direct calls to emlxs_XXXX_...._action() + * functions. Only emlxs_XXXX_action() routines may make calls to + * emlxs_XXXX_...._action() functions. + * + * - Its is forbidden to make direct calls to emlxs_XXXX_action(). + * Only emlxs_XXXX_state() and emlxs_XXXX_event() routines may make + * calls to emlxs_XXXX_action(). + * + * - The EMLXS_FCF_LOCK must be held before calling: + * emlxs_XXXX_state(), emlxs_XXXX_event() and emlxs_XXXX_action(). + * + * - All other calls touching fctab, fcfi, vfi, vpi, rpi objects must hold + * the EMLXS_FCF_LOCK to protect these objects. + */ + +/* ************************************************************************** */ +/* FCF Generic */ +/* ************************************************************************** */ + +/* + * EVENT ARG1 + * -------------------------------------------- + * FCF_EVENT_STATE_ENTER None + * + * FCF_EVENT_LINKUP None + * FCF_EVENT_LINKDOWN None + * FCF_EVENT_CVL vpi + * FCF_EVENT_FCFTAB_FULL None + * FCF_EVENT_FCF_FOUND fcf_index + * FCF_EVENT_FCF_LOST fcf_index + * FCF_EVENT_FCF_CHANGED fcf_index + * + * FCF_EVENT_FCFI_ONLINE FCFIobj_t* + * FCF_EVENT_FCFI_OFFLINE FCFIobj_t* + * FCF_EVENT_FCFI_PAUSE FCFIobj_t* + * + * FCF_EVENT_VFI_ONLINE VFIobj_t* + * FCF_EVENT_VFI_OFFLINE VFIobj_t* + * FCF_EVENT_VFI_PAUSE VFIobj_t* + * + * FCF_EVENT_VPI_ONLINE VPIobj_t* + * FCF_EVENT_VPI_OFFLINE VPIobj_t* + * FCF_EVENT_VPI_PAUSE VPIobj_t* + * + * FCF_EVENT_RPI_ONLINE RPIobj_t* + * FCF_EVENT_RPI_OFFLINE RPIobj_t* + * FCF_EVENT_RPI_PAUSE RPIobj_t* + * FCF_EVENT_RPI_RESUME RPIobj_t* + */ + +/* Order does not matter */ +emlxs_table_t emlxs_fcf_event_table[] = +{ + {FCF_EVENT_STATE_ENTER, "STATE_ENTER"}, + + {FCF_EVENT_SHUTDOWN, "SHUTDOWN"}, + {FCF_EVENT_LINKUP, "LINK_UP"}, + {FCF_EVENT_LINKDOWN, "LINK_DOWN"}, + {FCF_EVENT_CVL, "CVL_RECD"}, + {FCF_EVENT_FCFTAB_FULL, "TABLE_FULL"}, + {FCF_EVENT_FCF_FOUND, "FCF_FOUND"}, + {FCF_EVENT_FCF_LOST, "FCF_LOST"}, + {FCF_EVENT_FCF_CHANGED, "FCF_CHANGED"}, + + {FCF_EVENT_FCFI_ONLINE, "FCFI_ONLINE"}, + {FCF_EVENT_FCFI_OFFLINE, "FCFI_OFFLINE"}, + {FCF_EVENT_FCFI_PAUSE, "FCFI_PAUSE"}, + + {FCF_EVENT_VFI_ONLINE, "VFI_ONLINE"}, + {FCF_EVENT_VFI_OFFLINE, "VFI_OFFLINE"}, + {FCF_EVENT_VFI_PAUSE, "VFI_PAUSE"}, + + {FCF_EVENT_VPI_ONLINE, "VPI_ONLINE"}, + {FCF_EVENT_VPI_OFFLINE, "VPI_OFFLINE"}, + {FCF_EVENT_VPI_PAUSE, "VPI_PAUSE"}, + + {FCF_EVENT_RPI_ONLINE, "RPI_ONLINE"}, + {FCF_EVENT_RPI_OFFLINE, "RPI_OFFLINE"}, + {FCF_EVENT_RPI_PAUSE, "RPI_PAUSE"}, + {FCF_EVENT_RPI_RESUME, "RPI_RESUME"}, + +}; /* emlxs_fcf_event_table */ + + +/* Order does not matter */ +emlxs_table_t emlxs_fcf_reason_table[] = +{ + {FCF_REASON_NONE, "REASON_NONE"}, + {FCF_REASON_REENTER, "REASON_REENTER"}, + {FCF_REASON_EVENT, "REASON_EVENT"}, + {FCF_REASON_REQUESTED, "REASON_REQUESTED"}, + {FCF_REASON_NO_MBOX, "REASON_NO_MBOX"}, + {FCF_REASON_NO_BUFFER, "REASON_NO_BUFFER"}, + {FCF_REASON_SEND_FAILED, "REASON_SEND_FAILED"}, + {FCF_REASON_MBOX_FAILED, "REASON_MBOX_FAILED"}, + {FCF_REASON_NO_FCFI, "REASON_NO_FCFI"}, + {FCF_REASON_NO_VFI, "REASON_NO_VFI"}, + {FCF_REASON_ONLINE_FAILED, "REASON_ONLINE_FAILED"}, + {FCF_REASON_OFFLINE_FAILED, "REASON_OFFLINE_FAILED"}, + {FCF_REASON_OP_FAILED, "REASON_OP_FAILED"}, + {FCF_REASON_NO_PKT, "FCF_REASON_NO_PKT"}, + {FCF_REASON_NO_NODE, "FCF_REASON_NO_NODE"}, + {FCF_REASON_NOT_ALLOWED, "FCF_REASON_NOT_ALLOWED"}, + +}; /* emlxs_fcf_reason_table */ + + +/* ********************************************************************** */ +/* FCFTAB */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_fcftab_state_table[] = +{ + {FCFTAB_STATE_SHUTDOWN, "FCFTAB_STATE_SHUTDOWN"}, + {FCFTAB_STATE_OFFLINE, "FCFTAB_STATE_OFFLINE"}, + + {FCFTAB_STATE_SOLICIT, "FCFTAB_STATE_SOLICIT"}, + {FCFTAB_STATE_SOLICIT_FAILED, "FCFTAB_STATE_SOLICIT_FAILED"}, + {FCFTAB_STATE_SOLICIT_CMPL, "FCFTAB_STATE_SOLICIT_CMPL"}, + + {FCFTAB_STATE_READ, "FCFTAB_STATE_READ"}, + {FCFTAB_STATE_READ_FAILED, "FCFTAB_STATE_READ_FAILED"}, + {FCFTAB_STATE_READ_CMPL, "FCFTAB_STATE_READ_CMPL"}, + + {FCFTAB_STATE_FCFI_OFFLINE, "FCFTAB_STATE_FCFI_OFFLINE"}, + {FCFTAB_STATE_FCFI_OFFLINE_CMPL, "FCFTAB_STATE_FCFI_OFFLINE_CMPL"}, + + {FCFTAB_STATE_FCFI_ONLINE, "FCFTAB_STATE_FCFI_ONLINE"}, + {FCFTAB_STATE_FCFI_ONLINE_CMPL, "FCFTAB_STATE_FCFI_ONLINE_CMPL"}, + + {FCFTAB_STATE_ONLINE, "FCFTAB_STATE_ONLINE"}, + +}; /* emlxs_fcftab_state_table */ + + +static uint32_t emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_sol_failed_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_sol_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_read_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_read_failed_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_read_cmpl_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_online_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_found_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_lost_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_changed_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_full_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_linkup_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_cvl_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_online_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_offline_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port, + uint32_t evt, void *arg1); +static uint32_t emlxs_fcftab_shutdown_action(emlxs_port_t *port, + uint32_t evt, void *arg1); + +static void emlxs_fcftab_read_timer(emlxs_hba_t *hba); +static void emlxs_fcftab_sol_timer(emlxs_hba_t *hba); +static void emlxs_fcftab_offline_timer(emlxs_hba_t *hba); +static char *emlxs_fcftab_state_xlate(uint32_t state); +static uint32_t emlxs_fcftab_event(emlxs_port_t *port, + uint32_t evt, void *arg1); + +/* + * - Online sequencing can start from FCFI_STATE_OFFLINE state + * + * - Offline sequencing can interrupt the online sequencing at the + * entry of the next wait state. + * + * NORMAL ONLINE SEQ + * --------------------------- + * LINK_UP event <-- Adapter + * FCFTAB_STATE_OFFLINE + * FCFTAB_STATE_SOLICIT + * FCFTAB_STATE_SOLICIT_CMPL + * FCFTAB_STATE_READ + * FCFTAB_STATE_READ_CMPL + * FCFTAB_STATE_FCFI_OFFLINE + * FCFTAB_STATE_FCFI_OFFLINE_CMPL + * FCFTAB_STATE_FCFI_ONLINE + * FCFTAB_STATE_FCFI_ONLINE_CMPL + * FCFTAB_STATE_ONLINE + * + * + * NORMAL OFFLINE SEQ + * --------------------------- + * LINK_DOWN event <-- Adapter + * FCFTAB_STATE_ONLINE + * FCFTAB_STATE_FCFI_OFFLINE + * FCFTAB_STATE_FCFI_OFFLINE_CMPL + * FCFTAB_STATE_OFFLINE + * + */ +/* Order does matter */ +static void *emlxs_fcftab_action_table[] = +{ + /* Action routine Event */ +/* FCFTAB_STATE_SHUTDOWN 0 (Requires adapter reset) */ + (void *) emlxs_fcftab_shutdown_action, /* STATE_ENTER */ + (void *) NULL, /* SHUTDOWN */ + (void *) NULL, /* LINK_UP */ + (void *) NULL, /* LINK_DOWN */ + (void *) NULL, /* CVL_RECD */ + (void *) NULL, /* FCF_FOUND */ + (void *) NULL, /* FCF_LOST */ + (void *) NULL, /* FCF_CHANGED */ + (void *) NULL, /* TABLE_FULL */ + (void *) NULL, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_OFFLINE 1 (Wait for LINK_UP event) */ + (void *) emlxs_fcftab_offline_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + + +/* FCFTAB_STATE_SOLICIT 2 (Wait on fcf_solicit cmpl) */ + (void *) emlxs_fcftab_sol_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_SOLICIT_FAILED 3 (Transitional) */ + (void *) emlxs_fcftab_sol_failed_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_SOLICIT_CMPL 4 (Wait on fcf timer cmpl) */ + (void *) emlxs_fcftab_sol_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + + +/* FCFTAB_STATE_READ 5 (Wait on fcf_read cmpl) */ + (void *) emlxs_fcftab_read_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_READ_FAILED 6 (Transitional) */ + (void *) emlxs_fcftab_read_failed_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_READ_CMPL 7 (Transitional) */ + (void *) emlxs_fcftab_read_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + + +/* FCFTAB_STATE_FCFI_OFFLINE_CMPL 8 (Transitional) */ + (void *) emlxs_fcftab_fcfi_offline_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_FCFI_OFFLINE 9 (Wait for FCFI_OFFLINE event) */ + (void *) emlxs_fcftab_fcfi_offline_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + + +/* FCFTAB_STATE_FCFI_ONLINE 10 (Wait on FCFI_ONLINE event) */ + (void *) emlxs_fcftab_fcfi_online_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +/* FCFTAB_STATE_FCFI_ONLINE_CMPL 11 (Transitional) */ + (void *) emlxs_fcftab_fcfi_online_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + + +/* FCFTAB_STATE_ONLINE 12 (Wait for LINK_DOWN event) */ + (void *) emlxs_fcftab_online_action, /* STATE_ENTER */ + (void *) emlxs_fcftab_shutdown_evt_action, /* SHUTDOWN */ + (void *) emlxs_fcftab_linkup_evt_action, /* LINK_UP */ + (void *) emlxs_fcftab_linkdown_evt_action, /* LINK_DOWN */ + (void *) emlxs_fcftab_cvl_evt_action, /* CVL_RECD */ + (void *) emlxs_fcftab_found_evt_action, /* FCF_FOUND */ + (void *) emlxs_fcftab_lost_evt_action, /* FCF_LOST */ + (void *) emlxs_fcftab_changed_evt_action, /* FCF_CHANGED */ + (void *) emlxs_fcftab_full_evt_action, /* TABLE_FULL */ + (void *) emlxs_fcftab_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcftab_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + +}; /* emlxs_fcftab_action_table[] */ +#define FCFTAB_ACTION_EVENTS 11 +#define FCFTAB_ACTION_STATES \ + (sizeof (emlxs_fcftab_action_table)/ \ + (FCFTAB_ACTION_EVENTS * sizeof (void *))) + + +/* ********************************************************************** */ +/* VFTAB - This will be needed for multi-virtual fabric environments */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_vftab_state_table[] = +{ + {VFTAB_STATE_DISABLED, "VFTAB_STATE_DISABLED"}, + +}; /* emlxs_vftab_state_table */ + + + +/* ********************************************************************** */ +/* FCFI */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_fcfi_state_table[] = +{ + {FCFI_STATE_FREE, "FCFI_STATE_FREE"}, + + {FCFI_STATE_OFFLINE, "FCFI_STATE_OFFLINE"}, + + {FCFI_STATE_UNREG_CMPL, "FCFI_STATE_UNREG_CMPL"}, + {FCFI_STATE_UNREG_FAILED, "FCFI_STATE_UNREG_FAILED"}, + {FCFI_STATE_UNREG, "FCFI_STATE_UNREG"}, + + {FCFI_STATE_REG, "FCFI_STATE_REG"}, + {FCFI_STATE_REG_FAILED, "FCFI_STATE_REG_FAILED"}, + {FCFI_STATE_REG_CMPL, "FCFI_STATE_REG_CMPL"}, + + {FCFI_STATE_VFI_OFFLINE_CMPL, "FCFI_STATE_VFI_OFFLINE_CMPL"}, + {FCFI_STATE_VFI_OFFLINE, "FCFI_STATE_VFI_OFFLINE"}, + + {FCFI_STATE_VFI_ONLINE, "FCFI_STATE_VFI_ONLINE"}, + {FCFI_STATE_VFI_ONLINE_CMPL, "FCFI_STATE_VFI_ONLINE_CMPL"}, + + {FCFI_STATE_PAUSED, "FCFI_STATE_PAUSED"}, + {FCFI_STATE_ONLINE, "FCFI_STATE_ONLINE"}, + +}; /* emlxs_fcfi_state_table */ + + +static uint32_t emlxs_fcfi_free_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_online_evt_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_offline_evt_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_pause_evt_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_reg_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_unreg_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_online_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_reg_failed_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_online_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_paused_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_offline_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); +static uint32_t emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, + FCFIobj_t *fcfp, uint32_t evt, void *arg1); + +static uint32_t emlxs_fcfi_event(emlxs_port_t *port, + uint32_t evt, void *arg1); +static FCFIobj_t *emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, + uint32_t *fcf_index); +static FCFIobj_t *emlxs_fcfi_alloc(emlxs_port_t *port); +static uint32_t emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp); +static void emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, + FCF_RECORD_t *fcf_rec, uint32_t event_tag); +static char *emlxs_fcfi_state_xlate(uint32_t state); + +/* + * - Online sequencing can start from FCFI_STATE_OFFLINE state or + * the FCFI_STATE_VFI_OFFLINE state. + * + * - Offline sequencing can interrupt the online sequencing at the + * entry of the next wait state. + * + * NORMAL ONLINE SEQ + * --------------------------- + * FCFI_ONLINE event <-- FCFTAB + * FCFI_STATE_OFFLINE + * FCFI_STATE_REG + * FCFI_STATE_REG_CMPL + * FCFI_STATE_VFI_ONLINE + * FCFI_STATE_VFI_ONLINE_CMPL + * FCFI_STATE_ONLINE + * FCFI_ONLINE event-->FCFTAB + * + * + * NORMAL OFFLINE SEQ + * --------------------------- + * FCFI_OFFLINE event <-- FCFTAB + * FCFI_STATE_ONLINE + * FCFI_STATE_VFI_OFFLINE + * FCFI_STATE_VFI_OFFLINE_CMPL + * FCFI_STATE_UNREG + * FCFI_STATE_UNREG_CMPL + * FCFI_STATE_OFFLINE + * FCFI_OFFLINE event-->FCFTAB + * + * + * NORMAL PAUSE SEQ + * --------------------------- + * FCFI_PAUSE event <-- FCFTAB + * FCFI_STATE_ONLINE + * FCFI_STATE_PAUSED + * + */ +/* Order does matter */ +static void *emlxs_fcfi_action_table[] = +{ + /* Action routine Event */ +/* FCFI_STATE_FREE 0 (Wait for allocation) */ + (void *) emlxs_fcfi_free_action, /* STATE_ENTER */ + (void *) NULL, /* FCFI_ONLINE */ + (void *) NULL, /* FCFI_OFFLINE */ + (void *) NULL, /* FCFI_PAUSE */ + (void *) NULL, /* VFI_ONLINE */ + (void *) NULL, /* VFI_OFFLINE */ + +/* FCFI_STATE_OFFLINE 1 (Wait for FCFI_ONLINE event) */ + (void *) emlxs_fcfi_offline_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_UNREG_CMPL 2 (Transitional) */ + (void *) emlxs_fcfi_unreg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_UNREG_FAILED 3 (Transitional) */ + (void *) emlxs_fcfi_unreg_failed_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_UNREG 4 (Wait for unreg_fcfi cmpl) */ + (void *) emlxs_fcfi_unreg_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_REG 5 (Wait for reg_fcfi cmpl) */ + (void *) emlxs_fcfi_reg_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_REG_FAILED 6 (Transitional) */ + (void *) emlxs_fcfi_reg_failed_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_REG_CMPL 7 (Transitional) */ + (void *) emlxs_fcfi_reg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_VFI_OFFLINE_CMPL 8 (Transitional) */ + (void *) emlxs_fcfi_vfi_offline_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_VFI_OFFLINE 9 (Wait for VFI_OFFLINE event) */ + (void *) emlxs_fcfi_vfi_offline_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE * */ + +/* FCFI_STATE_VFI_ONLINE 10 (Wait for VFI_ONLINE event) */ + (void *) emlxs_fcfi_vfi_online_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_VFI_ONLINE_CMPL 11 (Transitional) */ + (void *) emlxs_fcfi_vfi_online_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + + +/* FCFI_STATE_PAUSED 12 (Wait for FCFI_ONLINE event) */ + (void *) emlxs_fcfi_paused_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +/* FCFI_STATE_ONLINE 13 (Wait for FCFI_OFFLINE event) */ + (void *) emlxs_fcfi_online_action, /* STATE_ENTER */ + (void *) emlxs_fcfi_online_evt_action, /* FCFI_ONLINE */ + (void *) emlxs_fcfi_offline_evt_action, /* FCFI_OFFLINE */ + (void *) emlxs_fcfi_pause_evt_action, /* FCFI_PAUSE */ + (void *) emlxs_fcfi_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_fcfi_vfi_offline_evt_action, /* VFI_OFFLINE */ + +}; /* emlxs_fcfi_action_table[] */ +#define FCFI_ACTION_EVENTS 6 +#define FCFI_ACTION_STATES \ + (sizeof (emlxs_fcfi_action_table)/ \ + (FCFI_ACTION_EVENTS * sizeof (void *))) + + +/* ********************************************************************** */ +/* VFI */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_vfi_state_table[] = +{ + {VFI_STATE_OFFLINE, "VFI_STATE_OFFLINE"}, + + {VFI_STATE_INIT, "VFI_STATE_INIT"}, + {VFI_STATE_INIT_FAILED, "VFI_STATE_INIT_FAILED"}, + {VFI_STATE_INIT_CMPL, "VFI_STATE_INIT_CMPL"}, + + {VFI_STATE_VPI_OFFLINE_CMPL, "VFI_STATE_VPI_OFFLINE_CMPL"}, + {VFI_STATE_VPI_OFFLINE, "VFI_STATE_VPI_OFFLINE"}, + + {VFI_STATE_VPI_ONLINE, "VFI_STATE_VPI_ONLINE"}, + {VFI_STATE_VPI_ONLINE_CMPL, "VFI_STATE_VPI_ONLINE_CMPL"}, + + {VFI_STATE_UNREG_CMPL, "VFI_STATE_UNREG_CMPL"}, + {VFI_STATE_UNREG_FAILED, "VFI_STATE_UNREG_FAILED"}, + {VFI_STATE_UNREG, "VFI_STATE_UNREG"}, + + {VFI_STATE_REG, "VFI_STATE_REG"}, + {VFI_STATE_REG_FAILED, "VFI_STATE_REG_FAILED"}, + {VFI_STATE_REG_CMPL, "VFI_STATE_REG_CMPL"}, + + {VFI_STATE_PAUSED, "VFI_STATE_PAUSED"}, + {VFI_STATE_ONLINE, "VFI_STATE_ONLINE"}, + +}; /* emlxs_vfi_state_table */ + + +static uint32_t emlxs_vfi_pause_evt_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_online_evt_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_offline_evt_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_init_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_init_failed_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_init_cmpl_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_offline_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_online_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_paused_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_online_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_offline_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_reg_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_reg_failed_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_unreg_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_unreg_failed_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); +static uint32_t emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, + VFIobj_t *vfip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vfi_event(emlxs_port_t *port, + uint32_t evt, void *arg1); + + +/* + * - Online sequencing can start from VFI_STATE_OFFLINE state or + * the VFI_STATE_VPI_OFFLINE state. + * + * - Offline sequencing can interrupt the online sequencing at the + * entry of the next wait state. + * + * NORMAL ONLINE SEQ + * --------------------------- + * VFI_ONLINE event <-- FCFI + * VFI_STATE_OFFLINE + * VFI_STATE_INIT + * VFI_STATE_INIT_CMPL + * VFI_STATE_VPI_ONLINE + * VFI_STATE_VPI_ONLINE_CMPL + * VFI_STATE_REG + * VFI_STATE_REG_CMPL + * VFI_STATE_ONLINE + * VFI_ONLINE event-->FCFI + * + * + * NORMAL OFFLINE SEQ + * --------------------------- + * VFI_OFFLINE event <-- FCFI + * VFI_STATE_ONLINE + * VFI_STATE_VPI_OFFLINE + * VFI_STATE_VPI_OFFLINE_CMPL + * VFI_STATE_UNREG + * VFI_STATE_UNREG_CMPL + * VFI_STATE_OFFLINE + * VFI_OFFLINE event-->FCFI + * + * + * NORMAL PAUSE SEQ + * --------------------------- + * VFI_PAUSE event <-- FCFI + * VFI_STATE_ONLINE + * VFI_STATE_PAUSED + * + */ +/* Order does matter */ +static void *emlxs_vfi_action_table[] = +{ + /* Action routine Event */ +/* VFI_STATE_OFFLINE 0 (Wait for VFI_ONLINE event) */ + (void *) emlxs_vfi_offline_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_INIT 1 (Wait for init_vfi cmpl) */ + (void *) emlxs_vfi_init_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_INIT_FAILED 2 (Transitional) */ + (void *) emlxs_vfi_init_failed_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_INIT_CMPL 3 (Transitional) */ + (void *) emlxs_vfi_init_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_VPI_OFFLINE_CMPL 4 (Wait for VPI_OFFLINE event) */ + (void *) emlxs_vfi_vpi_offline_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_VPI_OFFLINE 5 (Wait for VPI_OFFLINE event) */ + (void *) emlxs_vfi_vpi_offline_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_VPI_ONLINE 6 (Wait for VPI_ONLINE event) */ + (void *) emlxs_vfi_vpi_online_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_VPI_ONLINE_CMPL 7 (Transitional) */ + (void *) emlxs_vfi_vpi_online_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_UNREG_CMPL 8 (Transitional) */ + (void *) emlxs_vfi_unreg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_UNREG_FAILED 9 (Transitional) */ + (void *) emlxs_vfi_unreg_failed_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_UNREG 10 (Wait for unreg_vfi cmpl) */ + (void *) emlxs_vfi_unreg_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_REG 11 (Wait for reg_vfi cmpl) */ + (void *) emlxs_vfi_reg_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_REG_FAILED 12 (Transitional) */ + (void *) emlxs_vfi_reg_failed_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_REG_CMPL 13 (Transitional) */ + (void *) emlxs_vfi_reg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + + +/* VFI_STATE_PAUSED 14 (Wait for VFI_OFFLINE event) */ + (void *) emlxs_vfi_paused_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +/* VFI_STATE_ONLINE 14 (Wait for VFI_OFFLINE event) */ + (void *) emlxs_vfi_online_action, /* STATE_ENTER */ + (void *) emlxs_vfi_online_evt_action, /* VFI_ONLINE */ + (void *) emlxs_vfi_offline_evt_action, /* VFI_OFFLINE */ + (void *) emlxs_vfi_pause_evt_action, /* VFI_PAUSE */ + (void *) emlxs_vfi_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vfi_vpi_offline_evt_action, /* VPI_OFFLINE */ + +}; /* emlxs_vfi_action_table[] */ +#define VFI_ACTION_EVENTS 6 +#define VFI_ACTION_STATES \ + (sizeof (emlxs_vfi_action_table)/ \ + (VFI_ACTION_EVENTS * sizeof (void *))) + + +/* ********************************************************************** */ +/* VPI */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_vpi_state_table[] = +{ + {VPI_STATE_OFFLINE, "VPI_STATE_OFFLINE"}, + + {VPI_STATE_INIT, "VPI_STATE_INIT"}, + {VPI_STATE_INIT_FAILED, "VPI_STATE_INIT_FAILED"}, + {VPI_STATE_INIT_CMPL, "VPI_STATE_INIT_CMPL"}, + + {VPI_STATE_UNREG_CMPL, "VPI_STATE_UNREG_CMPL"}, + {VPI_STATE_UNREG_FAILED, "VPI_STATE_UNREG_FAILED"}, + {VPI_STATE_UNREG, "VPI_STATE_UNREG"}, + + {VPI_STATE_LOGO_CMPL, "VPI_STATE_LOGO_CMPL"}, + {VPI_STATE_LOGO_FAILED, "VPI_STATE_LOGO_FAILED"}, + {VPI_STATE_LOGO, "VPI_STATE_LOGO"}, + + {VPI_STATE_PORT_OFFLINE, "VPI_STATE_PORT_OFFLINE"}, + {VPI_STATE_PORT_ONLINE, "VPI_STATE_PORT_ONLINE"}, + + {VPI_STATE_LOGI, "VPI_STATE_LOGI"}, + {VPI_STATE_LOGI_FAILED, "VPI_STATE_LOGI_FAILED"}, + {VPI_STATE_LOGI_CMPL, "VPI_STATE_LOGI_CMPL"}, + + {VPI_STATE_REG, "VPI_STATE_REG"}, + {VPI_STATE_REG_FAILED, "VPI_STATE_REG_FAILED"}, + {VPI_STATE_REG_CMPL, "VPI_STATE_REG_CMPL"}, + + {VPI_STATE_PAUSED, "VPI_STATE_PAUSED"}, + {VPI_STATE_ONLINE, "VPI_STATE_ONLINE"}, + +}; /* emlxs_vpi_state_table */ + + +static uint32_t emlxs_vpi_online_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_offline_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_pause_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_init_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_init_failed_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_init_cmpl_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_offline_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_online_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_paused_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_port_online_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_port_offline_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_logi_failed_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_logi_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_reg_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_reg_failed_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_unreg_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_unreg_failed_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_logo_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_logo_failed_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); +static uint32_t emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, + VPIobj_t *vpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_vpi_event(emlxs_port_t *port, + uint32_t evt, void *arg1); +static void emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip, + uint32_t status); + +/* + * - Online sequencing can only start from VPI_STATE_OFFLINE or + * VPI_STATE_PORT_OFFLINE state. + * + * - Offline sequencing can interrupt the online sequencing at the + * entry of the next wait state. + * + * NORMAL ONLINE SEQ + * --------------------------- + * VPI_ONLINE event <-- VFI + * VPI_STATE_OFFLINE + * VPI_STATE_INIT + * VPI_STATE_INIT_CMPL + * VPI_STATE_PORT_ONLINE + * VPI_STATE_LOGI + * VPI_STATE_LOGI_CMPL + * VPI_STATE_REG + * VPI_STATE_REG_CMPL + * VPI_STATE_ONLINE + * VPI_ONLINE event-->VFI + * + * + * NORMAL OFFLINE SEQ + * --------------------------- + * VPI_OFFLINE event <-- VFI + * VPI_STATE_ONLINE + * VPI_STATE_PORT_OFFLINE + * VPI_STATE_LOGO + * VPI_STATE_LOGO_CMPL + * VPI_STATE_UNREG + * VPI_STATE_UNREG_CMPL + * VPI_STATE_OFFLINE + * VPI_OFFLINE event-->VFI + * + * + * NORMAL PAUSE SEQ + * --------------------------- + * VPI_PAUSE event <-- VFI + * VPI_STATE_ONLINE + * VPI_STATE_PORT_OFFLINE + * VPI_STATE_PAUSED + * + */ +/* Order does matter */ +static void *emlxs_vpi_action_table[] = +{ + /* Action routine Event */ +/* VPI_STATE_OFFLINE 0 (Wait for VPI_ONLINE event) */ + (void *) emlxs_vpi_offline_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_INIT 1 (Wait for init_vpi cmpl) */ + (void *) emlxs_vpi_init_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_INIT_FAILED 2 (Transitional) */ + (void *) emlxs_vpi_init_failed_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_INIT_CMPL 3 (Transitional) */ + (void *) emlxs_vpi_init_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_UNREG_CMPL 4 (Transitional) */ + (void *) emlxs_vpi_unreg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_UNREG_FAILED 5 (Transitional) */ + (void *) emlxs_vpi_unreg_failed_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_UNREG 6 (Wait for unreg_vpi cmpl) */ + (void *) emlxs_vpi_unreg_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_LOGO_CMPL 7 (Transitional) */ + (void *) emlxs_vpi_logo_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_LOGO_FAILED 8 (Transitional) */ + (void *) emlxs_vpi_logo_failed_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_LOGO 9 (Transitional) */ + (void *) emlxs_vpi_logo_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_PORT_OFFLINE 10 (Wait for RPI_OFFLINE or VPI_ONLINE) */ + (void *) emlxs_vpi_port_offline_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_PORT_ONLINE 11 (Wait for emlxs_vpi_logi_notify() ) */ + (void *) emlxs_vpi_port_online_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_LOGI 12 (Wait for emlxs_vpi_logi_cmpl_notify() ) */ + (void *) emlxs_vpi_logi_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_LOGI_FAILED 13 (Transitional) */ + (void *) emlxs_vpi_logi_failed_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_LOGI_CMPL 14 (Transitional) */ + (void *) emlxs_vpi_logi_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_REG 15 (Wait for reg_vpi cmpl) */ + (void *) emlxs_vpi_reg_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_REG_FAILED 16 (Transitional) */ + (void *) emlxs_vpi_reg_failed_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_REG_CMPL 17 (Transitional) */ + (void *) emlxs_vpi_reg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + + +/* VPI_STATE_PAUSED 18 (Wait for VPI_ONLINE() ) */ + (void *) emlxs_vpi_paused_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +/* VPI_STATE_ONLINE 19 (Wait for VPI_OFFLINE event) */ + (void *) emlxs_vpi_online_action, /* STATE_ENTER */ + (void *) emlxs_vpi_online_evt_action, /* VPI_ONLINE */ + (void *) emlxs_vpi_offline_evt_action, /* VPI_OFFLINE */ + (void *) emlxs_vpi_pause_evt_action, /* VPI_PAUSE */ + (void *) emlxs_vpi_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_vpi_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_vpi_rpi_pause_evt_action, /* RPI_PAUSE */ + +}; /* emlxs_vpi_action_table() */ +#define VPI_ACTION_EVENTS 7 +#define VPI_ACTION_STATES \ + (sizeof (emlxs_vpi_action_table)/ \ + (VPI_ACTION_EVENTS * sizeof (void *))) + + +/* ********************************************************************** */ +/* RPI */ +/* ********************************************************************** */ + +/* Order does not matter */ +emlxs_table_t emlxs_rpi_state_table[] = +{ + {RPI_STATE_FREE, "RPI_STATE_FREE"}, + + {RPI_STATE_OFFLINE, "RPI_STATE_OFFLINE"}, + + {RPI_STATE_UNREG_CMPL, "RPI_STATE_UNREG_CMPL"}, + {RPI_STATE_UNREG_FAILED, "RPI_STATE_UNREG_FAILED"}, + {RPI_STATE_UNREG, "RPI_STATE_UNREG"}, + + {RPI_STATE_REG, "RPI_STATE_REG"}, + {RPI_STATE_REG_FAILED, "RPI_STATE_REG_FAILED"}, + {RPI_STATE_REG_CMPL, "RPI_STATE_REG_CMPL"}, + + {RPI_STATE_PAUSED, "RPI_STATE_PAUSED"}, + + {RPI_STATE_RESUME, "RPI_STATE_RESUME"}, + {RPI_STATE_RESUME_FAILED, "RPI_STATE_RESUME_FAILED"}, + {RPI_STATE_RESUME_CMPL, "RPI_STATE_RESUME_CMPL"}, + + {RPI_STATE_ONLINE, "RPI_STATE_ONLINE"}, + +}; /* emlxs_rpi_state_table */ + +static uint32_t emlxs_rpi_free_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_online_evt_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_offline_evt_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_pause_evt_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_resume_evt_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_reg_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_reg_failed_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_unreg_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_unreg_failed_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_online_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_paused_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_offline_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_resume_failed_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); +static uint32_t emlxs_rpi_resume_action(emlxs_port_t *port, + RPIobj_t *rpip, uint32_t evt, void *arg1); + +static uint32_t emlxs_rpi_event(emlxs_port_t *port, + uint32_t evt, void *arg1); +static RPIobj_t *emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did); +static uint32_t emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip); +static RPIobj_t *emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did); + +static void emlxs_rpi_resume_handler(emlxs_port_t *port, + RPIobj_t *rpip); +static void emlxs_rpi_unreg_handler(emlxs_port_t *port, + RPIobj_t *rpip); +static uint32_t emlxs_rpi_reg_handler(emlxs_port_t *port, + RPIobj_t *rpip); +/* + * - Online sequencing can start from RPI_STATE_OFFLINE state or + * the RPI_STATE_PAUSED state. + * + * - Offline sequencing can interrupt the online sequencing at the + * entry of the next wait state. + * + * NORMAL ONLINE SEQ + * --------------------------- + * RPI_ONLINE event <-- VPI + * RPI_STATE_OFFLINE + * RPI_STATE_REG + * RPI_STATE_REG_CMPL + * RPI_STATE_ONLINE + * RPI_ONLINE event-->VPI + * + * + * NORMAL OFFLINE SEQ + * --------------------------- + * RPI_OFFLINE event <-- VPI + * RPI_STATE_ONLINE + * RPI_STATE_UNREG + * RPI_STATE_UNREG_CMPL + * RPI_STATE_OFFLINE + * RPI_OFFLINE event-->VPI + * + * + * NORMAL PAUSE SEQ + * --------------------------- + * RPI_PAUSE event <-- VPI + * RPI_STATE_ONLINE + * RPI_STATE_PAUSED + * + */ +/* Order does matter */ +static void *emlxs_rpi_action_table[] = +{ + /* Action routine Event */ +/* RPI_STATE_FREE 0 (Wait for allocation) */ + (void *) emlxs_rpi_free_action, /* STATE_ENTER */ + (void *) NULL, /* RPI_ONLINE */ + (void *) NULL, /* RPI_OFFLINE */ + (void *) NULL, /* RPI_PAUSE */ + (void *) NULL, /* RPI_RESUME */ + +/* RPI_STATE_OFFLINE 1 (Wait for RPI_ONLINE event) */ + (void *) emlxs_rpi_offline_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_UNREG_CMPL 2 (Transitional) */ + (void *) emlxs_rpi_unreg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_UNREG_FAILED 3 (Transitional) */ + (void *) emlxs_rpi_unreg_failed_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_UNREG 4 (Wait for unreg_rpi cmpl) */ + (void *) emlxs_rpi_unreg_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + + +/* RPI_STATE_REG 5 (Wait for reg_rpi cmpl) */ + (void *) emlxs_rpi_reg_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_REG_FAILED 6 (Transitional) */ + (void *) emlxs_rpi_reg_failed_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_REG_CMPL 7 (Transitional) */ + (void *) emlxs_rpi_reg_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + + +/* RPI_STATE_PAUSED 8 (Wait for RPI_ONLINE) */ + (void *) emlxs_rpi_paused_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + + +/* RPI_STATE_RESUME 9 (Wait for resume_rpi mbcmpl) */ + (void *) emlxs_rpi_resume_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_RESUME_FAILED 10 (Transitional) */ + (void *) emlxs_rpi_resume_failed_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +/* RPI_STATE_RESUME_CMPL 11 (Transitional) */ + (void *) emlxs_rpi_resume_cmpl_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + + +/* RPI_STATE_ONLINE 12 (Wait for RPI_OFFLINE event) */ + (void *) emlxs_rpi_online_action, /* STATE_ENTER */ + (void *) emlxs_rpi_online_evt_action, /* RPI_ONLINE */ + (void *) emlxs_rpi_offline_evt_action, /* RPI_OFFLINE */ + (void *) emlxs_rpi_pause_evt_action, /* RPI_PAUSE */ + (void *) emlxs_rpi_resume_evt_action, /* RPI_RESUME */ + +}; /* emlxs_rpi_action_table[] */ +#define RPI_ACTION_EVENTS 5 +#define RPI_ACTION_STATES \ + (sizeof (emlxs_rpi_action_table)/ \ + (RPI_ACTION_EVENTS * sizeof (void *))) + + +/* ************************************************************************** */ +/* FCF Generic */ +/* ************************************************************************** */ + +extern void +emlxs_fcf_fini(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + emlxs_port_t *vport; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t i; + RPIobj_t *rpip; + + if (!fcftab->table) { + return; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "emlxs_fcf_fini: %s flag=%x fcfi_online=%d.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->flag, fcftab->fcfi_online); + + if (fcftab->state != FCFTAB_STATE_SHUTDOWN) { + (void) emlxs_fcf_shutdown_notify(port, 1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + /* Free the FCF memory */ + + kmem_free(fcftab->table, + (sizeof (FCFIobj_t) * fcftab->table_count)); + + fcftab->table = NULL; + fcftab->table_count = 0; + + /* Free the VFI memory */ + + kmem_free(hba->sli.sli4.VFI_table, + (sizeof (VFIobj_t) * hba->sli.sli4.VFICount)); + + hba->sli.sli4.VFI_table = NULL; + hba->sli.sli4.VFICount = 0; + + /* Free the VPI Fabric RPI's */ + + for (i = 0; i < MAX_VPORTS; i++) { + vport = &VPORT(i); + rpip = &vport->VPIobj.fcf_rpi; + + if (rpip->state == RPI_STATE_FREE) { + continue; + } + + (void) emlxs_rpi_free(port, rpip); + } + + /* Free the RPI memory */ + + rpip = hba->sli.sli4.RPIp; + for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { + if (rpip->state == RPI_STATE_FREE) { + continue; + } + + (void) emlxs_rpi_free(port, rpip); + } + + kmem_free(hba->sli.sli4.RPIp, + (sizeof (RPIobj_t) * hba->sli.sli4.RPICount)); + + hba->sli.sli4.RPIp = NULL; + hba->sli.sli4.RPICount = 0; + + /* Free the mutex */ + + mutex_exit(&EMLXS_FCF_LOCK); + mutex_destroy(&EMLXS_FCF_LOCK); + + return; + +} /* emlxs_fcf_fini() */ + + +extern void +emlxs_fcf_init(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + emlxs_port_t *vport; + uint16_t i; + FCFIobj_t *fcfp; + VFIobj_t *vfip; + RPIobj_t *rpip; + char buf[64]; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint16_t index; + + if (fcftab->table) { + return; + } + + /* FCFTAB */ + + bzero(fcftab, sizeof (FCFTable_t)); + + (void) sprintf(buf, "%s_fcf_lock mutex", DRIVER_NAME); + mutex_init(&EMLXS_FCF_LOCK, buf, MUTEX_DRIVER, NULL); + mutex_enter(&EMLXS_FCF_LOCK); + + fcftab->state = FCFTAB_STATE_OFFLINE; + + /* FCFI */ + + fcftab->table_count = hba->sli.sli4.FCFICount; + fcftab->table = (FCFIobj_t *)kmem_zalloc( + (sizeof (FCFIobj_t) * fcftab->table_count), KM_SLEEP); + + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + fcfp->index = i; + fcfp->FCFI = 0xFFFF; + fcfp->state = FCFI_STATE_FREE; + } + + /* VFI */ + + hba->sli.sli4.VFI_table = (VFIobj_t *)kmem_zalloc( + (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP); + + vfip = hba->sli.sli4.VFI_table; + index = hba->sli.sli4.VFIBase; + for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++, index++) { + vfip->VFI = index; + vfip->index = i; + vfip->state = VPI_STATE_OFFLINE; + } + + /* VPI */ + + for (i = 0; i < MAX_VPORTS; i++) { + vport = &VPORT(i); + bzero(&vport->VPIobj, sizeof (VPIobj_t)); + + vport->VPIobj.index = i; + vport->VPIobj.VPI = i + hba->sli.sli4.VPIBase; + vport->VPIobj.port = vport; + vport->VPIobj.state = VPI_STATE_OFFLINE; + + /* Init the Fabric RPI's */ + rpip = &vport->VPIobj.fcf_rpi; + rpip->state = RPI_STATE_FREE; + rpip->RPI = 0xffff; + rpip->index = 0xffff; + rpip->did = FABRIC_DID; + rpip->vpip = &vport->VPIobj; + vport->VPIobj.rpip = rpip; + } + + /* RPI */ + + hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc( + (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP); + + rpip = hba->sli.sli4.RPIp; + index = hba->sli.sli4.RPIBase; + for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++, index++) { + rpip->state = RPI_STATE_FREE; + rpip->RPI = index; + rpip->index = i; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "emlxs_fcf_init: %s flag=%x fcfi=%d vfi=%d vpi=%d rpi=%d", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->flag, + fcftab->table_count, + hba->sli.sli4.VFICount, + MAX_VPORTS, + hba->sli.sli4.RPICount); + + mutex_exit(&EMLXS_FCF_LOCK); + + return; + +} /* emlxs_fcf_init() */ + + +static char * +emlxs_fcf_event_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_fcf_event_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_fcf_event_table[i].code) { + return (emlxs_fcf_event_table[i].string); + } + } + + (void) sprintf(buffer, "event=0x%x", state); + return (buffer); + +} /* emlxs_fcf_event_xlate() */ + + +static char * +emlxs_fcf_reason_xlate(uint32_t reason) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_fcf_reason_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (reason == emlxs_fcf_reason_table[i].code) { + return (emlxs_fcf_reason_table[i].string); + } + } + + (void) sprintf(buffer, "reason=0x%x", reason); + return (buffer); + +} /* emlxs_fcf_reason_xlate() */ + + +extern void +emlxs_fcf_timer_notify(emlxs_hba_t *hba) +{ + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return; + } + + if (fcftab->table == 0) { + return; + } + + mutex_enter(&EMLXS_FCF_LOCK); + + emlxs_fcftab_sol_timer(hba); + + emlxs_fcftab_read_timer(hba); + + emlxs_fcftab_offline_timer(hba); + + mutex_exit(&EMLXS_FCF_LOCK); + + return; + +} /* emlxs_fcf_timer_notify() */ + + +extern uint32_t +emlxs_fcf_shutdown_notify(emlxs_port_t *port, uint32_t wait) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + uint32_t i; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_SHUTDOWN, 0); + + if (wait && (rval == 0)) { + /* Wait for FCF table to shutdown */ + i = 0; + while (i++ < 120) { + if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) { + break; + } + + mutex_exit(&EMLXS_FCF_LOCK); + DELAYMS(1000); + mutex_enter(&EMLXS_FCF_LOCK); + } + + if (i >= 120) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcf_shutdown_notify: %s flag=%x fcfi_online=%d. " + "Shutdown timeout.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->flag, fcftab->fcfi_online); + } + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_shutdown_notify() */ + + +extern uint32_t +emlxs_fcf_linkup_notify(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_LINKUP, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_linkup_notify() */ + + +extern uint32_t +emlxs_fcf_linkdown_notify(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_LINKDOWN, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_linkdown_notify() */ + + +extern uint32_t +emlxs_fcf_cvl_notify(emlxs_port_t *port, uint32_t vpi) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_CVL, + (void *)((uintptr_t)vpi)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_cvl_notify() */ + + +extern uint32_t +emlxs_fcf_full_notify(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_FCFTAB_FULL, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_full_notify() */ + + +extern uint32_t +emlxs_fcf_found_notify(emlxs_port_t *port, uint32_t fcf_index) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_FOUND, + (void *)((uintptr_t)fcf_index)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_found_notify() */ + + +extern uint32_t +emlxs_fcf_changed_notify(emlxs_port_t *port, uint32_t fcf_index) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_CHANGED, + (void *)((uintptr_t)fcf_index)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_changed_notify() */ + + +extern uint32_t +emlxs_fcf_lost_notify(emlxs_port_t *port, uint32_t fcf_index) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *pport = &PPORT; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!(pport->flag & EMLXS_PORT_BOUND)) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_fcftab_event(port, FCF_EVENT_FCF_LOST, + (void *)((uintptr_t)fcf_index)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_fcf_lost_notify() */ + + + +/* ************************************************************************** */ +/* FCFTAB */ +/* ************************************************************************** */ + +static char * +emlxs_fcftab_state_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_fcftab_state_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_fcftab_state_table[i].code) { + return (emlxs_fcftab_state_table[i].string); + } + } + + (void) sprintf(buffer, "state=0x%x", state); + return (buffer); + +} /* emlxs_fcftab_state_xlate() */ + + +static uint32_t +emlxs_fcftab_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + uint32_t(*func) (emlxs_port_t *, uint32_t, void *); + uint32_t index; + uint32_t events; + uint16_t state; + + /* Convert event to action table index */ + switch (evt) { + case FCF_EVENT_STATE_ENTER: + index = 0; + break; + case FCF_EVENT_SHUTDOWN: + index = 1; + break; + case FCF_EVENT_LINKUP: + index = 2; + break; + case FCF_EVENT_LINKDOWN: + index = 3; + break; + case FCF_EVENT_CVL: + index = 4; + break; + case FCF_EVENT_FCF_FOUND: + index = 5; + break; + case FCF_EVENT_FCF_LOST: + index = 6; + break; + case FCF_EVENT_FCF_CHANGED: + index = 7; + break; + case FCF_EVENT_FCFTAB_FULL: + index = 8; + break; + case FCF_EVENT_FCFI_ONLINE: + index = 9; + break; + case FCF_EVENT_FCFI_OFFLINE: + index = 10; + break; + default: + return (1); + } + + events = FCFTAB_ACTION_EVENTS; + state = fcftab->state; + + index += (state * events); + func = (uint32_t(*) (emlxs_port_t *, uint32_t, void *)) + emlxs_fcftab_action_table[index]; + + if (!func) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcftab: %s:%s arg=%p. No action. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + rval = (func)(port, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_action() */ + + +static uint32_t +emlxs_fcftab_event(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + /* Filter events */ + switch (evt) { + case FCF_EVENT_SHUTDOWN: + case FCF_EVENT_LINKUP: + case FCF_EVENT_LINKDOWN: + case FCF_EVENT_CVL: + case FCF_EVENT_FCF_FOUND: + case FCF_EVENT_FCF_LOST: + case FCF_EVENT_FCF_CHANGED: + case FCF_EVENT_FCFTAB_FULL: + case FCF_EVENT_FCFI_OFFLINE: + case FCF_EVENT_FCFI_ONLINE: + break; + + default: + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcftab: %s:%s arg=%p.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcftab_action(port, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_event() */ + + +/* EMLXS_FCF_LOCK must be held to enter */ +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_state(emlxs_port_t *port, uint16_t state, uint16_t reason, + uint32_t explain, void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + + if (state >= FCFTAB_ACTION_STATES) { + return (1); + } + + if ((fcftab->state == state) && + (reason != FCF_REASON_REENTER)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_state: %s:%s:0x%x arg=%p. " + "State not changed. Terminated.", + emlxs_fcftab_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + + return (1); + } + + if (!reason) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcftab:%s-->%s arg=%p", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcftab_state_xlate(state), arg1); + } else if (reason == FCF_REASON_EVENT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcftab:%s-->%s:%s:%s arg=%p", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcftab_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + emlxs_fcf_event_xlate(explain), arg1); + } else if (explain) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcftab:%s-->%s:%s:0x%x arg=%p", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcftab_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcftab:%s-->%s:%s arg=%p", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcftab_state_xlate(state), + emlxs_fcf_reason_xlate(reason), arg1); + } + + fcftab->prev_state = fcftab->state; + fcftab->prev_reason = fcftab->reason; + fcftab->state = state; + fcftab->reason = reason; + + rval = emlxs_fcftab_action(port, FCF_EVENT_STATE_ENTER, arg1); + + return (rval); + +} /* emlxs_fcftab_state() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_offline_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + FCFIobj_t *fcfp; + + if (evt != FCF_EVENT_FCFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_offline_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + fcfp = (FCFIobj_t *)arg1; + + switch (fcftab->state) { + case FCFTAB_STATE_SHUTDOWN: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_evt_action:%d. Shutting down.", + fcfp->fcf_index); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN, + FCF_REASON_REENTER, evt, arg1); + break; + + case FCFTAB_STATE_FCFI_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_evt_action:%d. Offlining.", + fcfp->fcf_index); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case FCFTAB_STATE_FCFI_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_evt_action:%d. Attempting failover.", + fcfp->fcf_index); + + fcfp->flag |= EMLXS_FCFI_FAILED; + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case FCFTAB_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_evt_action:%d.", + fcfp->fcf_index); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_evt_action:%d %s. Terminated.", + fcfp->fcf_index, + emlxs_fcftab_state_xlate(fcftab->state)); + break; + } + + return (rval); + +} /* emlxs_fcftab_fcfi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_online_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + FCFIobj_t *fcfp; + + if (evt != FCF_EVENT_FCFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_online_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + fcfp = (FCFIobj_t *)arg1; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_evt_action:%d. Terminated.", + fcfp->fcf_index); + + return (rval); + +} /* emlxs_fcftab_fcfi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_cvl_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + emlxs_port_t *vport; + uint32_t vpi; + VPIobj_t *vpip; + + if (evt != FCF_EVENT_CVL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_cvl_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + /* Pause VPI */ + vpi = (uint32_t)((uintptr_t)arg1); + vport = &VPORT(vpi); + vpip = &vport->VPIobj; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_cvl_evt_action: %s gen=%x. Pausing VPI:%d.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation, + vpip->VPI); + + rval = emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip); + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_cvl_evt_action: %s gen=%x. " + "Already soliciting. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + break; + + default: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_cvl_evt_action: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_cvl_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_linkup_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + emlxs_config_t *cfg = &CFG; + + if (evt != FCF_EVENT_LINKUP) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_linkup_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkup_evt_action: %s:%s arg=%p gen=%x. Link up.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->generation); + + mutex_enter(&EMLXS_PORT_LOCK); + if (hba->state < FC_LINK_UP) { + HBASTATS.LinkUp++; + EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); + } + hba->discovery_timer = + hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + + cfg[CFG_DISC_TIMEOUT].current; + mutex_exit(&EMLXS_PORT_LOCK); + + emlxs_log_link_event(port); + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkup_evt_action: %s gen=%x. " + "Already soliciting. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + break; + + default: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkup_evt_action: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_linkup_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_linkdown_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + int32_t i; + FCFIobj_t *fcfp; + + if (evt != FCF_EVENT_LINKDOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_OFFLINE_REQ; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkdown_evt_action: %s:%s arg=%p flag=%x. Linkdown.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + mutex_enter(&EMLXS_PORT_LOCK); + if (hba->state > FC_LINK_DOWN) { + HBASTATS.LinkDown++; + EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); + } + hba->flag &= FC_LINKDOWN_MASK; + hba->discovery_timer = 0; + mutex_exit(&EMLXS_PORT_LOCK); + + emlxs_log_link_event(port); + + /* Pause all active FCFI's */ + for (i = 0; i < fcftab->fcfi_count; i++) { + fcfp = fcftab->fcfi[i]; + + if ((fcfp->state == FCFI_STATE_OFFLINE) || + (fcfp->state == FCFI_STATE_PAUSED)) { + break; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkdown_evt_action: Pausing FCFI:%d.", + fcfp->fcf_index); + + (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_PAUSE, fcfp); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_linkdown_evt_action: Going offline."); + + switch (fcftab->state) { + case FCFTAB_STATE_OFFLINE: + rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_linkdown_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_shutdown_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + + if (evt != FCF_EVENT_SHUTDOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_SHUTDOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " + "Already shut down. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + if (fcftab->state == FCFTAB_STATE_SHUTDOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " + "Already shutting down. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_evt_action: %s:%s arg=%p flag=%x. " + "Shutting down.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + if (hba->state > FC_LINK_DOWN) { + mutex_enter(&EMLXS_PORT_LOCK); + if (hba->state > FC_LINK_DOWN) { + HBASTATS.LinkDown++; + EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); + } + hba->flag &= FC_LINKDOWN_MASK; + hba->discovery_timer = 0; + mutex_exit(&EMLXS_PORT_LOCK); + + emlxs_log_link_event(port); + } + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SHUTDOWN, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_shutdown_evt_action() */ + + +static uint32_t +emlxs_fcftab_req_handler(emlxs_port_t *port, void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + + if (!(fcftab->flag & EMLXS_FCFTAB_REQ_MASK)) { + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_OFFLINE_REQ) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_OFFLINE, + FCF_REASON_REQUESTED, 0, arg1); + } + + else if (fcftab->flag & EMLXS_FCFTAB_SOL_REQ) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_REQUESTED, 0, arg1); + } + + else if (fcftab->flag & EMLXS_FCFTAB_READ_REQ) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, + FCF_REASON_REQUESTED, 0, FCFTAB_READ_ALL); + } + + return (rval); + +} /* emlxs_fcftab_req_handler() */ + + +static void +emlxs_fcftab_read_timer(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + + /* Check FCF timer */ + if (!fcftab->read_timer || + (hba->timer_tics <= fcftab->read_timer)) { + return; + } + fcftab->read_timer = 0; + fcftab->flag |= EMLXS_FCFTAB_READ_REQ; + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT_CMPL: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_timer: %s", + emlxs_fcftab_state_xlate(fcftab->state)); + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ, 0, 0, + FCFTAB_READ_ALL); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_timer: %s Terminated.", + emlxs_fcftab_state_xlate(fcftab->state)); + break; + } + + return; + +} /* emlxs_fcftab_read_timer() */ + + +static void +emlxs_fcftab_sol_timer(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + + /* Check FCF timer */ + if (!fcftab->sol_timer || + (hba->timer_tics <= fcftab->sol_timer)) { + return; + } + fcftab->sol_timer = 0; + + switch (fcftab->state) { + case FCFTAB_STATE_ONLINE: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_timer: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, 0, 0); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_timer: %s Terminated.", + emlxs_fcftab_state_xlate(fcftab->state)); + break; + } + + return; + +} /* emlxs_fcftab_sol_timer() */ + + +static void +emlxs_fcftab_offline_timer(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t i; + FCFIobj_t *fcfp; + + for (i = 0; i < fcftab->fcfi_count; i++) { + fcfp = fcftab->fcfi[i]; + + /* Check offline timer */ + if (!fcfp->offline_timer || + (hba->timer_tics <= fcfp->offline_timer)) { + continue; + } + fcfp->offline_timer = 0; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_offline_timer:%d %s. Offlining.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + + (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp); + } + + return; + +} /* emlxs_fcftab_offline_timer() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_sol_failed_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + fcftab->attempts++; + + if (fcftab->state != FCFTAB_STATE_SOLICIT_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + arg1, fcftab->attempts); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_failed_action: %s:%s arg=%p attempt=%d reason=%x", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->attempts, + fcftab->reason); + + if ((fcftab->reason == FCF_REASON_SEND_FAILED) || + (fcftab->attempts >= 3)) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL, + FCF_REASON_OP_FAILED, 0, arg1); + } else { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_OP_FAILED, 0, arg1); + } + + return (rval); + +} /* emlxs_fcftab_sol_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_sol_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; + uint32_t generation; + mbox_rsp_hdr_t *hdr_rsp; + MATCHMAP *mp; + uint32_t status = MGMT_STATUS_FCF_IN_USE; + uint32_t xstatus = 0; + uint32_t fip_mode = 1; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (mbq->nonembed) { + fip_mode = 0; + + mp = (MATCHMAP *)mbq->nonembed; + mbq->nonembed = NULL; + + hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; + status = hdr_rsp->status; + xstatus = hdr_rsp->extra_status; + + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + } + + if (fcftab->state != FCFTAB_STATE_SOLICIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_mbcmpl: %s. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + generation = (uint32_t)((uintptr_t)mbq->context); + if (generation != fcftab->generation) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_mbcmpl: %s gen=%x,%x. " + "Incorrect generation. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + generation, fcftab->generation); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + if (fip_mode) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_mbcmpl:failed. status=%x", + mb4->mbxStatus); + + (void) emlxs_fcftab_state(port, + FCFTAB_STATE_SOLICIT_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + + } else if ((status == 0)||(status != MGMT_STATUS_FCF_IN_USE)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_mbcmpl:failed. status=%x,%x,%x", + mb4->mbxStatus, status, + xstatus); + + (void) emlxs_fcftab_state(port, + FCFTAB_STATE_SOLICIT_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_mbcmpl: %s gen=%x", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_fcftab_sol_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_sol_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOXQ *mbq; + MAILBOX4 *mb4; + MATCHMAP *mp = NULL; + uint32_t rval; + + if (fcftab->state != FCFTAB_STATE_SOLICIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_sol_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if ((fcftab->prev_state != FCFTAB_STATE_SOLICIT_FAILED) || + (fcftab->flag & EMLXS_FCFTAB_SOL_REQ)) { + fcftab->flag &= ~EMLXS_FCFTAB_SOL_REQ; + fcftab->attempts = 0; + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_action: %s:%s arg=%p gen=%d flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->generation, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_action: %s:%s arg = %p gen=%x fip=%x. " + "Requesting solicit.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->generation, + ((hba->flag & FC_FIP_SUPPORTED)? 1:0)); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED, + FCF_REASON_NO_MBOX, 0, 0); + return (rval); + } + + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + if (hba->flag & FC_FIP_SUPPORTED) { + IOCTL_FCOE_REDISCOVER_FCF_TABLE *fcf; + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl; + mbq->context = (void *)((uintptr_t)fcftab->generation); + mbq->port = (void *)port; + + mb4->un.varSLIConfig.be.embedded = 1; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = + sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE) + + IOCTL_HEADER_SZ; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + IOCTL_SUBSYSTEM_FCOE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = + FCOE_OPCODE_REDISCOVER_FCF_TABLE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + sizeof (IOCTL_FCOE_REDISCOVER_FCF_TABLE); + + fcf = (IOCTL_FCOE_REDISCOVER_FCF_TABLE *) + &mb4->un.varSLIConfig.payload; + fcf->params.request.fcf_count = 0; /* invalidate FCF table */ + + } else { /* Non-FIP */ + + /* Non-FIP uses a persistent FCF entry that */ + /* we must add to the table */ + + IOCTL_FCOE_ADD_FCF_TABLE *fcf; + mbox_req_hdr_t *hdr_req; + FCF_RECORD_t *fcf_rec; + uint8_t bitmap[512]; + uint16_t i; + + if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcftab_state(port, + FCFTAB_STATE_SOLICIT_FAILED, + FCF_REASON_NO_BUFFER, 0, arg1); + return (rval); + } + bzero(mp->virt, mp->size); + + mbq->nonembed = (void *)mp; + mbq->mbox_cmpl = emlxs_fcftab_sol_mbcmpl; + mbq->context = (void *)((uintptr_t)fcftab->generation); + mbq->port = (void *)port; + + mb4->un.varSLIConfig.be.embedded = 0; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + + hdr_req = (mbox_req_hdr_t *)mp->virt; + hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; + hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE; + hdr_req->timeout = 0; + hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE); + + fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1); + fcf->params.request.fcf_index = 0; + + fcf_rec = &fcf->params.request.fcf_entry; + fcf_rec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ; + fcf_rec->fka_adv_period = 0; + fcf_rec->fip_priority = 128; + +#ifdef EMLXS_BIG_ENDIAN + fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3; + fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2; + fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1; + fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0; + fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC5; + fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC4; + fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2]; + fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; + fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0]; +#endif /* EMLXS_BIG_ENDIAN */ +#ifdef EMLXS_LITTLE_ENDIAN + fcf_rec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0; + fcf_rec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1; + fcf_rec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2; + fcf_rec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3; + fcf_rec->fcf_mac_address_low[0] = FCOE_FCF_MAC4; + fcf_rec->fcf_mac_address_low[1] = FCOE_FCF_MAC5; + fcf_rec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0]; + fcf_rec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; + fcf_rec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2]; +#endif /* EMLXS_LITTLE_ENDIAN */ + + if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) { + bzero((void *) bitmap, 512); + i = hba->sli.sli4.cfgFCOE.VLanId; + bitmap[i / 8] = (1 << (i % 8)); + BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512); + } else { + bzero((void *) bitmap, 512); + bitmap[0] = 1; /* represents bit 0 */ + BE_SWAP32_BCOPY(bitmap, fcf_rec->vlan_bitmap, 512); + } + + fcf_rec->fcf_valid = 1; + fcf_rec->fcf_available = 1; + } + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + if (mp) { + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + } + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT_FAILED, + FCF_REASON_SEND_FAILED, rval, 0); + + return (rval); + } + + return (0); + + +} /* emlxs_fcftab_sol_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_sol_cmpl_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + emlxs_config_t *cfg = &CFG; + + if (fcftab->state != FCFTAB_STATE_SOLICIT_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_sol_cmpl_action: %s:%s arg=%p " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + /* Increment the generation counter */ + fcftab->generation++; + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->generation, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_sol_cmpl_action: %s:%s arg=%p gen=%d. " + "Starting timer (%d secs).", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->generation, + cfg[CFG_FCF_SOLICIT_DELAY].current); + + /* Start the read timer */ + fcftab->read_timer = hba->timer_tics + + cfg[CFG_FCF_SOLICIT_DELAY].current; + + return (0); + +} /* emlxs_fcftab_sol_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_read_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; + mbox_rsp_hdr_t *hdr_rsp; + IOCTL_FCOE_READ_FCF_TABLE *fcf; + FCF_RECORD_t *fcfrec; + FCFIobj_t *fcfp; + MATCHMAP *mp; + uint32_t index; + uint32_t event_tag; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (fcftab->state != FCFTAB_STATE_READ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_mbcmpl: state=%s. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + index = (uint32_t)((uintptr_t)mbq->context); + mp = (MATCHMAP *)mbq->nonembed; + hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; + + if (mb4->mbxStatus || hdr_rsp->status) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_mbcmpl:%d failed. status=%x,%x,%x", + index, mb4->mbxStatus, hdr_rsp->status, + hdr_rsp->extra_status); + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_mbcmpl: state=%s", + emlxs_fcftab_state_xlate(fcftab->state)); + + fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1); + fcfrec = &fcf->params.response.fcf_entry[0]; + +#ifdef EMLXS_BIG_ENDIAN +{ + uint32_t *iptr; + uint32_t i; + uint8_t j; + uint16_t s; + uint16_t *sptr; + + /* Fix up data in FCF record */ + SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8); + SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8); + SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512); + + iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0]; + i = *iptr; + *iptr = SWAP32(i); + + sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0]; + s = *sptr; + *sptr = SWAP16(s); + + j = fcfrec->fc_map[0]; + fcfrec->fc_map[0] = fcfrec->fc_map[2]; + fcfrec->fc_map[2] = j; +} +#endif /* EMLXS_BIG_ENDIAN */ + + event_tag = fcf->params.response.event_tag; + + /* Try to find existing fcfrec */ + fcfp = emlxs_fcfi_find(port, fcfrec, 0); + + /* If not found, allocate a new one */ + if (!fcfp) { + fcfp = emlxs_fcfi_alloc(port); + } + + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_mbcmpl:%d failed. Unable to allocate fcfi.", + index); + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, + FCF_REASON_NO_FCFI, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + /* Update the FCFI */ + emlxs_fcfi_update(port, fcfp, fcfrec, event_tag); + + /* Check if another record needs to be acquired */ + if (fcf->params.response.next_valid_fcf_index != 0xffff) { + fcftab->index = fcf->params.response.next_valid_fcf_index; + + (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ, + FCF_REASON_REENTER, 0, + (void *)((uintptr_t)fcf->params.response. + next_valid_fcf_index)); + } else { + (void) emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL, + 0, 0, 0); + } + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_fcftab_read_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_read_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOXQ *mbq; + MAILBOX4 *mb4; + IOCTL_FCOE_READ_FCF_TABLE *fcf; + uint32_t rval; + MATCHMAP *mp; + mbox_req_hdr_t *hdr_req; + uint16_t index; + + if (fcftab->state != FCFTAB_STATE_READ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_read_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + fcftab->flag &= ~EMLXS_FCFTAB_READ_REQ; + + if (fcftab->prev_state != FCFTAB_STATE_READ_FAILED) { + fcftab->attempts = 0; + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_action: %s:%s arg=%p flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + index = (uint16_t)((uintptr_t)arg1); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_action: %s:%s arg=%p attempts=%d. Reading FCF.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, + FCF_REASON_NO_BUFFER, 0, arg1); + return (rval); + } + bzero(mp->virt, mp->size); + + mbq->nonembed = (void *)mp; + mbq->mbox_cmpl = emlxs_fcftab_read_mbcmpl; + mbq->context = (void *)((uintptr_t)index); + mbq->port = (void *)port; + + mb4->un.varSLIConfig.be.embedded = 0; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + + hdr_req = (mbox_req_hdr_t *)mp->virt; + hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; + hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE; + hdr_req->timeout = 0; + hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE); + + fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1); + fcf->params.request.fcf_index = index; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_fcftab_read_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_read_failed_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + fcftab->attempts++; + + if (fcftab->state != FCFTAB_STATE_READ_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_read_failed_action: %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + arg1, fcftab->attempts); + + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_failed_action: %s:%s arg=%p attempt=%d reason=%x", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->attempts, + fcftab->reason); + + if ((fcftab->reason == FCF_REASON_SEND_FAILED) || + (fcftab->attempts >= 3)) { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ_CMPL, + FCF_REASON_OP_FAILED, fcftab->attempts, arg1); + } else { + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, + FCF_REASON_OP_FAILED, fcftab->attempts, FCFTAB_READ_ALL); + } + + return (rval); + +} /* emlxs_fcftab_read_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_read_cmpl_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + FCFIobj_t *fcfp; + uint32_t i; + + if (fcftab->state != FCFTAB_STATE_READ_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_read_cmpl_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_cmpl_action: %s:%s arg=%p attempts=%d. " + "Cleaning table.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->attempts); + + /* Clean FCFI table */ + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + /* Adjust the freshness flag */ + if (fcfp->generation == fcftab->generation) { + fcfp->flag |= EMLXS_FCFI_FRESH; + } else { + fcfp->flag &= ~EMLXS_FCFI_FRESH; + } + + /* Clear the failed bit */ + fcfp->flag &= ~EMLXS_FCFI_FAILED; + + /* Free all stale unselected entries now */ + if (!(fcfp->flag & EMLXS_FCFI_FRESH) && + !(fcfp->flag & EMLXS_FCFI_SELECTED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_read_cmpl_action:%d %s. " + "FCF stale. Freeing FCF.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + + (void) emlxs_fcfi_free(port, fcfp); + continue; + } + } + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_read_cmpl_action() */ + + +static FCFIobj_t * +emlxs_fcftab_fcfi_select(emlxs_port_t *port, char *fabric_wwn) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + FCFIobj_t *fcfp1; + uint32_t mask; + uint32_t viable; + uint32_t i; + uint32_t j; + uint32_t rnum; + timespec_t time; + FCFIobj_t **fcf_table; + uint32_t fcf_table_count; + + mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH| + EMLXS_FCFI_FAILED|EMLXS_FCFI_SELECTED); + viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH); + + /* Tag & count viable entries */ + fcf_table_count = 0; + fcfp = 0; + fcfp1 = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp1++) { + if (fcfp1->state == FCFI_STATE_FREE) { + fcfp1->flag &= ~EMLXS_FCFI_TAGGED; + continue; + } + + if ((fcfp1->flag & mask) != viable) { + fcfp1->flag &= ~EMLXS_FCFI_TAGGED; + continue; + } + + if (fabric_wwn && + bcmp(fabric_wwn, + fcfp1->fcf_rec.fabric_name_identifier, 8)) { + fcfp1->flag &= ~EMLXS_FCFI_TAGGED; + continue; + } + + fcfp1->flag |= EMLXS_FCFI_TAGGED; + fcfp = fcfp1; + fcf_table_count++; + } + + if (fcf_table_count == 0) { + return (NULL); + } + + if (fcf_table_count == 1) { + return (fcfp); + } + + /* We found more than one viable entry */ + + fcf_table = (FCFIobj_t **)kmem_zalloc( + (sizeof (uintptr_t) * fcf_table_count), KM_SLEEP); + + /* Find the highest priority tagged entry(s) */ + for (i = 0; i < fcf_table_count; i++) { + fcfp = 0; + fcfp1 = fcftab->table; + for (j = 0; j < fcftab->table_count; j++, fcfp1++) { + if (!(fcfp1->flag & EMLXS_FCFI_TAGGED)) { + continue; + } + + if (!fcfp || + (fcfp1->priority > fcfp->priority)) { + fcfp = fcfp1; + } + } + + if (fcf_table[0] && + (fcf_table[0]->priority > fcfp->priority)) { + break; + } + + fcfp->flag &= ~EMLXS_FCFI_TAGGED; + fcf_table[i] = fcfp; + } + + /* If more than one entry has the highest priority, */ + /* then randomly select one of the highest. */ + if (i > 1) { + /* Pick a random number from 0 to (i-1) */ + /* This algorithm uses the lower 16 bits of the nanosecond */ + /* clock to determine the value */ + bzero(&time, sizeof (timespec_t)); + gethrestime(&time); + rnum = (uint32_t)(time.tv_nsec & 0xFFFF); + + fcfp = fcf_table[(rnum%i)]; + } else { + fcfp = fcf_table[0]; + } + + /* Free the priority table */ + kmem_free(fcf_table, (sizeof (uintptr_t) * fcf_table_count)); + + return (fcfp); + +} /* emlxs_fcftab_fcfi_select() */ + + +/*ARGSUSED*/ +static void +emlxs_fcftab_process(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + FCFIobj_t *prev_fcfp; + uint32_t i; + uint32_t j; + uint32_t count; + uint32_t mask; + uint32_t viable; + emlxs_config_t *cfg = &CFG; + + mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH| + EMLXS_FCFI_FAILED); + viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED|EMLXS_FCFI_FRESH); + + /* Deselection process */ + for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { + fcfp = fcftab->fcfi[i]; + + if (!fcfp) { + continue; + } + + /* Check if entry is viable */ + if ((fcfp->flag & mask) == viable) { + if (fcfp->offline_timer) { + fcfp->offline_timer = 0; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "FCF viable. Offline timer disabled.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + cfg[CFG_FCF_FAILOVER_DELAY].current); + } + continue; + } + + /* Previous entry is no longer viable */ + + /* If FCF is still online */ + if (fcfp->state > FCFI_STATE_OFFLINE) { + if (fcfp->offline_timer == 0) { + /* Set the offline timer */ + fcfp->offline_timer = hba->timer_tics + + cfg[CFG_FCF_FAILOVER_DELAY].current; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "No longer viable. " + "Offlining FCF (%d secs).", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + cfg[CFG_FCF_FAILOVER_DELAY].current); + } + continue; + } + + /* Deselect it */ + fcfp->flag &= ~EMLXS_FCFI_SELECTED; + + if (!(fcfp->flag & EMLXS_FCFI_FRESH)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "No longer viable. Freeing FCF.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + + (void) emlxs_fcfi_free(port, fcfp); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "No longer viable. FCF deselected.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + } + } + + /* Reselection process */ + for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { + prev_fcfp = fcftab->fcfi[i]; + fcftab->fcfi[i] = NULL; + + /* If no previous selection, then make new one */ + if (!prev_fcfp) { + /* Select an fcf on any fabric */ + fcfp = emlxs_fcftab_fcfi_select(port, 0); + + if (fcfp) { + fcfp->flag |= EMLXS_FCFI_SELECTED; + fcftab->fcfi[i] = fcfp; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "New FCF selected.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d. No FCF available.", + i); + } + continue; + } + + /* If previous entry is still selected, keep it */ + if (prev_fcfp->flag & EMLXS_FCFI_SELECTED) { + fcfp = prev_fcfp; + fcftab->fcfi[i] = fcfp; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "FCF still selected.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + continue; + } + + /* Previous entry is no longer selected */ + + /* Select a new fcf from same fabric */ + fcfp = emlxs_fcftab_fcfi_select(port, + (char *)prev_fcfp->fcf_rec.fabric_name_identifier); + + if (fcfp) { + fcfp->flag |= EMLXS_FCFI_SELECTED; + fcftab->fcfi[i] = fcfp; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "New FCF, same fabric selected.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + continue; + } + + /* Select fcf from any fabric */ + fcfp = emlxs_fcftab_fcfi_select(port, 0); + + if (fcfp) { + fcfp->flag |= EMLXS_FCFI_SELECTED; + fcftab->fcfi[i] = fcfp; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d fcfi=%d %s. " + "New FCF, new fabric selected.", + i, fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_process:%d. No FCF available.", + i); + } + + /* Pack entries */ + count = 0; + for (i = 0; i < FCFTAB_MAX_FCFI_COUNT; i++) { + if (fcftab->fcfi[i]) { + count++; + continue; + } + + for (j = i+1; j < FCFTAB_MAX_FCFI_COUNT; j++) { + if (fcftab->fcfi[j] == NULL) { + continue; + } + + fcftab->fcfi[i] = fcftab->fcfi[j]; + fcftab->fcfi[j] = NULL; + count++; + break; + } + + if (j == FCFTAB_MAX_FCFI_COUNT) { + break; + } + } + fcftab->fcfi_count = count; + + return; + +} /* emlxs_fcftab_process() */ + + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_online_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t rval = 0; + uint32_t i; + uint32_t offline_count = 0; + uint32_t online_count = 0; + + if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_action: %s:%s arg=%p flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + emlxs_fcftab_process(port); + + for (i = 0; i < fcftab->fcfi_count; i++) { + fcfp = fcftab->fcfi[i]; + + if (fcfp->offline_timer == 0) { + online_count++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_action: fcfi_count=%d. " + "Onlining FCF:%d.", + fcftab->fcfi_count, + fcfp->fcf_index); + + (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_ONLINE, + fcfp); + } else { + offline_count++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_action: fcfi_count=%d. " + "Offlining FCF:%d.", + fcftab->fcfi_count, + fcfp->fcf_index); + } + } + + if (offline_count) { + /* Wait for FCF's to go offline */ + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + /* Service timer now */ + emlxs_fcftab_offline_timer(hba); + + return (rval); + } + + if (!online_count) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_action: fcfi_count=%d.", + fcftab->fcfi_count); + } + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_fcfi_online_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_online_cmpl_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + if (fcftab->state != FCFTAB_STATE_FCFI_ONLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_online_cmpl_action: %s:%s arg=%p", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_fcfi_online_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_offline_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t rval; + int32_t i; + uint32_t fcfi_offline; + + if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_offline_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + /* Check for FCF's going offline */ + fcfi_offline = 0; + for (i = 0; i < fcftab->fcfi_count; i++) { + fcfp = fcftab->fcfi[i]; + + if (fcfp->state <= FCFI_STATE_OFFLINE) { + continue; + } + + if (fcfp->offline_timer || + (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { + fcfi_offline++; + } + } + + if (fcfi_offline) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_action: %s:%s arg=%p " + "fcfi_offline=%d. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcfi_offline); + + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_action: %s:%s arg=%p.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_OFFLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + return (rval); + +} /* emlxs_fcftab_fcfi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcfi_offline_cmpl_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + if (fcftab->state != FCFTAB_STATE_FCFI_OFFLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcfi_offline_cmpl_action: %s:%s arg=%p.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_FCFI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcftab_fcfi_offline_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_found_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); + FCFIobj_t *fcfp; + uint32_t rval = 0; + + if (evt != FCF_EVENT_FCF_FOUND) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_found_evt_action: %s:%s fcf_index=%d. " + "Invalid event type. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (1); + } + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + case FCFTAB_STATE_SOLICIT_CMPL: + case FCFTAB_STATE_READ: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_found_evt_action: %s:%s fcf_index=%d gen=%x. " + "Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index, fcftab->generation); + break; + + /* case FCFTAB_STATE_FCFI_OFFLINE: */ + default: + + /* Scan for matching fcf index in table */ + fcfp = emlxs_fcfi_find(port, 0, &fcf_index); + + if (fcfp && (fcfp->flag & EMLXS_FCFI_SELECTED)) { + + /* Trigger table read */ + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_READ_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_found_evt_action: %s:%s fcf_index=%d " + "gen=%x. Read FCF table.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index, fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, + FCF_REASON_EVENT, evt, arg1); + + break; + } + + /* Check if we need more FCF's */ + if (fcftab->fcfi_online < FCFTAB_MAX_FCFI_COUNT) { + + /* Trigger table read */ + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_READ_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_found_evt_action: %s:%s fcf_index=%d " + "gen=%x fcfi_online=%d. Read FCF table.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index, fcftab->generation, + fcftab->fcfi_online); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_READ, + FCF_REASON_EVENT, evt, arg1); + + break; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_found_evt_action: %s:%s fcfi=%d. " + "FCF not needed. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + break; + } + + return (rval); + +} /* emlxs_fcftab_found_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_lost_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); + emlxs_port_t *vport; + VPIobj_t *vpip; + uint32_t i; + uint32_t rval; + + if (evt != FCF_EVENT_FCF_LOST) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_lost_evt_action: %s:%s fcf_index=%d. " + "Invalid event type. Terminated", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (1); + } + + /* Scan for matching fcf index in table */ + fcfp = emlxs_fcfi_find(port, 0, &fcf_index); + + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_lost_evt_action: %s:%s fcf_index=%d. " + "FCF not found. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (0); + } + + if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s:%s fcf_index=%d. " + "FCF not selected. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (0); + } + + /* Offline VPI's of this FCFI */ + for (i = 0; i <= hba->vpi_max; i++) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if ((vpip->state == VPI_STATE_OFFLINE) || + (vpip->vfip->fcfp != fcfp)) { + continue; + } + + /* Fabric logo is implied */ + vpip->flag &= ~EMLXS_VPI_LOGI; + if (vpip->flag & EMLXS_VPI_VFI_LOGI) { + vpip->flag &= ~EMLXS_VPI_VFI_LOGI; + + if (vpip->vfip->logi_count > 0) { + vpip->vfip->logi_count--; + } + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_lost_evt_action: %s:%s fcf_index=%d gen=%x. " + "Offlining VPI:%d.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index, fcftab->generation, + vpip->VPI); + + (void) emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); + } + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_lost_evt_action: %s gen=%x. " + "Already soliciting. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + break; + + default: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_lost_evt_action: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_lost_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_changed_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t fcf_index = (uint32_t)((uintptr_t)arg1); + uint32_t rval; + + if (evt != FCF_EVENT_FCF_CHANGED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s:%s fcf_index=%d. " + "Invalid event type. Terminated", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (1); + } + + /* Scan for matching fcf index in table */ + fcfp = emlxs_fcfi_find(port, 0, &fcf_index); + + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s:%s fcf_index=%d. " + "FCFI not found. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (1); + } + + if (!(fcfp->flag & EMLXS_FCFI_SELECTED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s:%s fcf_index=%d. " + "FCFI not selected. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcf_index); + + return (1); + } + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s gen=%x. " + "Already soliciting. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + break; + + default: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_changed_evt_action: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_changed_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_fcf_delete(emlxs_port_t *port, uint32_t fcf_index) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOXQ *mbq; + MAILBOX4 *mb4; + MATCHMAP *mp = NULL; + uint32_t rval; + + IOCTL_FCOE_DELETE_FCF_TABLE *fcf; + mbox_req_hdr_t *hdr_req; + + if (fcf_index >= fcftab->fcfi_count) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcf_delete:%d failed. Out of range.", + fcf_index); + + return (1); + } + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcf_delete:%d failed. Unable to allocate mailbox.", + fcf_index); + + return (1); + } + + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcf_delete:%d failed. Unable to allocate buffer.", + fcf_index); + + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + return (1); + } + bzero(mp->virt, mp->size); + + mbq->nonembed = (void *)mp; + mbq->mbox_cmpl = NULL; + mbq->context = (void *)((uintptr_t)fcf_index); + mbq->port = (void *)port; + + mb4->un.varSLIConfig.be.embedded = 0; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + + hdr_req = (mbox_req_hdr_t *)mp->virt; + hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; + hdr_req->opcode = FCOE_OPCODE_DELETE_FCF_TABLE; + hdr_req->timeout = 0; + hdr_req->req_length = sizeof (IOCTL_FCOE_DELETE_FCF_TABLE); + + fcf = (IOCTL_FCOE_DELETE_FCF_TABLE *)(hdr_req + 1); + fcf->params.request.fcf_count = 1; + fcf->params.request.fcf_indexes[0] = (uint16_t)fcf_index; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcf_delete:%d.", + fcf_index); + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_fcf_delete:%d failed. Unable to send request.", + fcf_index); + + if (mp) { + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + } + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + return (1); + } + + return (0); + + +} /* emlxs_fcftab_fcf_delete() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_full_evt_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t rval; + uint32_t mask; + uint32_t viable; + uint32_t i; + uint32_t count; + + if (evt != FCF_EVENT_FCFTAB_FULL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s:%s arg=%p. " + "Invalid event type. Terminated", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (fcftab->fcfi_online == FCFTAB_MAX_FCFI_COUNT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. " + "Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->fcfi_online); + + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s:%s arg=%p fcfi_online=%d. " + "Cleaning table...", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->fcfi_online); + + mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED); + viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED); + + count = 0; + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + if (fcfp->flag & EMLXS_FCFI_SELECTED) { + continue; + } + + if ((fcfp->flag & mask) == viable) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: fcfi=%d %s flag=%x. " + "Deleting FCF.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + fcfp->flag); + + (void) emlxs_fcfi_free(port, fcfp); + + (void) emlxs_fcftab_fcf_delete(port, fcfp->fcf_index); + + count++; + } + + if (!count) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s:%s arg=%p. " + "All FCF's are viable. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (0); + } + + switch (fcftab->state) { + case FCFTAB_STATE_SOLICIT: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s gen=%x. " + "Already soliciting. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + break; + + default: + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + fcftab->flag |= EMLXS_FCFTAB_SOL_REQ; + fcftab->generation++; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_full_evt_action: %s gen=%x. Soliciting.", + emlxs_fcftab_state_xlate(fcftab->state), + fcftab->generation); + + rval = emlxs_fcftab_state(port, FCFTAB_STATE_SOLICIT, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_fcftab_full_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_online_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + emlxs_config_t *cfg = &CFG; + FCFIobj_t *fcfp; + uint32_t rval; + uint32_t mask; + uint32_t viable; + uint32_t i; + uint32_t count = 0; + + if (fcftab->state != FCFTAB_STATE_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_online_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_online_action: %s:%s arg=%p flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + if (fcftab->fcfi_online == 0) { + mask = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED); + viable = (EMLXS_FCFI_VALID|EMLXS_FCFI_AVAILABLE| + EMLXS_FCFI_CONFIGURED); + + /* Count viable FCF's in table */ + count = 0; + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + if ((fcfp->flag & mask) == viable) { + count++; + } + } + + if (count) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_online_action: %s:%s " + "fcfi_online=0,%d,%d. Starting solicit timer.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcftab->fcfi_count, count); + + /* Start the solicit timer */ + fcftab->sol_timer = hba->timer_tics + + cfg[CFG_FCF_RESOLICIT_DELAY].current; + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_online_action: %s:%s " + "fcfi_online=0,%d,0. Wait for FCF event.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), + fcftab->fcfi_count); + } + + if (hba->state > FC_LINK_DOWN) { + mutex_enter(&EMLXS_PORT_LOCK); + if (hba->state > FC_LINK_DOWN) { + HBASTATS.LinkDown++; + EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); + } + hba->flag &= FC_LINKDOWN_MASK; + hba->discovery_timer = 0; + mutex_exit(&EMLXS_PORT_LOCK); + + emlxs_log_link_event(port); + } + + return (0); + } + + if (hba->state < FC_LINK_UP) { + mutex_enter(&EMLXS_PORT_LOCK); + if (hba->state < FC_LINK_UP) { + HBASTATS.LinkUp++; + EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_UP); + } + hba->discovery_timer = + hba->timer_tics + cfg[CFG_LINKUP_TIMEOUT].current + + cfg[CFG_DISC_TIMEOUT].current; + mutex_exit(&EMLXS_PORT_LOCK); + + emlxs_log_link_event(port); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_online_action: %s:%s arg=%p fcfi_online=%d. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->fcfi_online); + + return (0); + +} /* emlxs_fcftab_online_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_offline_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + if (fcftab->state != FCFTAB_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_offline_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + fcftab->flag &= ~EMLXS_FCFTAB_OFFLINE_REQ; + + if (fcftab->flag & EMLXS_FCFTAB_REQ_MASK) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_offline_action: %s:%s arg=%p flag=%x. " + "Handling request.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag); + + rval = emlxs_fcftab_req_handler(port, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_offline_action: %s:%s arg=%p fcfi_online=%d. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->fcfi_online); + + return (0); + +} /* emlxs_fcftab_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcftab_shutdown_action(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + FCFIobj_t *fcfp; + uint32_t i; + uint32_t online; + + if (fcftab->state != FCFTAB_STATE_SHUTDOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcftab_shutdown_action: %s:%s arg=%p. " + "Invalid state. Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + fcftab->flag &= ~EMLXS_FCFTAB_REQ_MASK; + + if (fcftab->prev_state != FCFTAB_STATE_SHUTDOWN) { + /* Offline all FCF's */ + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + + if (fcfp->state <= FCFI_STATE_OFFLINE) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_action: fcfi=%d %s " + "fcfi_online=%d. Offlining FCF.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + fcftab->fcfi_online); + + (void) emlxs_fcfi_event(port, FCF_EVENT_FCFI_OFFLINE, + fcfp); + } + + return (0); + } + + /* Check FCF state */ + online = 0; + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + + if (fcfp->state <= FCFI_STATE_OFFLINE) { + continue; + } + + online++; + } + + if (online) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_action: %s:%s arg=%p. " + "fcfi_online=%d,%d Terminated.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + online, fcftab->fcfi_online); + + return (0); + } + + /* Free FCF table */ + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + (void) emlxs_fcfi_free(port, fcfp); + } + + /* Clean the selection table */ + bzero(fcftab->fcfi, sizeof (fcftab->fcfi)); + fcftab->fcfi_count = 0; + + fcftab->flag |= EMLXS_FCFTAB_SHUTDOWN; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcftab_shutdown_action: %s:%s arg=%p flag=%x fcfi_online=%d. " + "Shutdown.", + emlxs_fcftab_state_xlate(fcftab->state), + emlxs_fcf_event_xlate(evt), arg1, + fcftab->flag, fcftab->fcfi_online); + + return (0); + +} /* emlxs_fcftab_shutdown_action() */ + + + +/* ************************************************************************** */ +/* FCFI */ +/* ************************************************************************** */ + +static char * +emlxs_fcfi_state_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_fcfi_state_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_fcfi_state_table[i].code) { + return (emlxs_fcfi_state_table[i].string); + } + } + + (void) sprintf(buffer, "state=0x%x", state); + return (buffer); + +} /* emlxs_fcfi_state_xlate() */ + + +static uint32_t +emlxs_fcfi_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + uint32_t(*func) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *); + uint32_t index; + uint32_t events; + uint16_t state; + + /* Convert event to action table index */ + switch (evt) { + case FCF_EVENT_STATE_ENTER: + index = 0; + break; + case FCF_EVENT_FCFI_ONLINE: + index = 1; + break; + case FCF_EVENT_FCFI_OFFLINE: + index = 2; + break; + case FCF_EVENT_FCFI_PAUSE: + index = 3; + break; + case FCF_EVENT_VFI_ONLINE: + index = 4; + break; + case FCF_EVENT_VFI_OFFLINE: + index = 5; + break; + default: + return (1); + } + + events = FCFI_ACTION_EVENTS; + state = fcfp->state; + + index += (state * events); + func = (uint32_t(*) (emlxs_port_t *, FCFIobj_t *, uint32_t, void *)) + emlxs_fcfi_action_table[index]; + + if (!func) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcfi:%d %s:%s arg=%p. No action. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + rval = (func)(port, fcfp, evt, arg1); + + return (rval); + +} /* emlxs_fcfi_action() */ + + +static uint32_t +emlxs_fcfi_event(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + FCFIobj_t *fcfp = NULL; + VFIobj_t *vfip = NULL; + uint32_t rval; + + /* Filter events and acquire fcfi context */ + switch (evt) { + case FCF_EVENT_VFI_ONLINE: + case FCF_EVENT_VFI_OFFLINE: + vfip = (VFIobj_t *)arg1; + + if (!vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcfi: %s arg=%p. Null VFI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + fcfp = vfip->fcfp; + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcfi: %s arg=%p. FCF not found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + break; + + case FCF_EVENT_FCFI_ONLINE: + case FCF_EVENT_FCFI_OFFLINE: + case FCF_EVENT_FCFI_PAUSE: + fcfp = (FCFIobj_t *)arg1; + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcfi: %s arg=%p. Null FCFI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + break; + + default: + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "fcfi:%d %s:%s arg=%p", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_fcfi_action(port, fcfp, evt, arg1); + + return (rval); + +} /* emlxs_fcfi_event() */ + + +/* EMLXS_FCF_LOCK must be held to enter */ +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_state(emlxs_port_t *port, FCFIobj_t *fcfp, uint16_t state, + uint16_t reason, uint32_t explain, void *arg1) +{ + uint32_t rval = 0; + + if (state >= FCFI_ACTION_STATES) { + return (1); + } + + if ((fcfp->state == state) && + (reason != FCF_REASON_REENTER)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_state:%d %s:%s:0x%x arg=%p. " + "State not changed. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + + return (1); + } + + if (!reason) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcfi:%d %s-->%s arg=%p", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcfi_state_xlate(state), arg1); + } else if (reason == FCF_REASON_EVENT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcfi:%d %s-->%s:%s:%s arg=%p", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + emlxs_fcf_event_xlate(explain), arg1); + } else if (explain) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcfi:%d %s-->%s:%s:0x%x arg=%p", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "fcfi:%d %s-->%s:%s arg=%p", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), arg1); + } + + fcfp->prev_state = fcfp->state; + fcfp->prev_reason = fcfp->reason; + fcfp->state = state; + fcfp->reason = reason; + + rval = emlxs_fcfi_action(port, fcfp, FCF_EVENT_STATE_ENTER, arg1); + + return (rval); + +} /* emlxs_fcfi_state() */ + + +static FCFIobj_t * +emlxs_fcfi_alloc(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint16_t i; + FCFIobj_t *fcfp; + + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + + bzero(fcfp, sizeof (FCFIobj_t)); + fcfp->index = i; + fcfp->FCFI = 0xFFFF; + + (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, + 0, 0, 0); + return (fcfp); + } + } + + return (NULL); + +} /* emlxs_fcfi_alloc() */ + + +static uint32_t +emlxs_fcfi_free(emlxs_port_t *port, FCFIobj_t *fcfp) +{ + uint32_t rval; + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_FREE, 0, 0, 0); + + return (rval); + +} /* emlxs_fcfi_free() */ + + +static FCFIobj_t * +emlxs_fcfi_find(emlxs_port_t *port, FCF_RECORD_t *fcfrec, uint32_t *fcf_index) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t i; + uint32_t index; + FCFIobj_t *fcfp; + + if (fcfrec) { + /* Check for a matching FCF index, fabric name, */ + /* and mac address */ + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + if ((fcfp->fcf_index == fcfrec->fcf_index) && + (bcmp((char *)fcfrec->fabric_name_identifier, + fcfp->fcf_rec.fabric_name_identifier, 8) == 0) && + (bcmp((char *)fcfrec->fcf_mac_address_hi, + fcfp->fcf_rec.fcf_mac_address_hi, 4) == 0) && + (bcmp((char *)fcfrec->fcf_mac_address_low, + fcfp->fcf_rec.fcf_mac_address_low, 2) == 0)) { + return (fcfp); + } + } + + } else if (fcf_index) { + /* Check for a matching FCF index only */ + index = *fcf_index; + fcfp = fcftab->table; + for (i = 0; i < fcftab->table_count; i++, fcfp++) { + if (fcfp->state == FCFI_STATE_FREE) { + continue; + } + + if (fcfp->fcf_index == index) { + return (fcfp); + } + } + } + + return (NULL); + +} /* emlxs_fcfi_find() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_free_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + + if (fcfp->state != FCFI_STATE_FREE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_free_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcfp->vfi_online) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_free_action:%d flag=%x vfi_online=%d", + fcfp->fcf_index, + fcfp->flag, + fcfp->vfi_online); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_free_action:%d flag=%x. FCF freed.", + fcfp->fcf_index, + fcfp->flag); + + fcfp->flag = 0; + + return (0); + +} /* emlxs_fcfi_free_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval; + + if (fcfp->state != FCFI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); + + if (fcfp->prev_state == FCFI_STATE_FREE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_action:%d fcfi_online=%d. Terminated.", + fcfp->fcf_index, + fcftab->fcfi_online); + + return (0); + } + + if (fcfp->vfi_online) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_offline_action:%d vfi_online=%d.", + fcfp->fcf_index, + fcfp->vfi_online); + } + + if (fcfp->flag & EMLXS_FCFI_FCFTAB) { + fcfp->flag &= ~EMLXS_FCFI_FCFTAB; + + if (fcftab->fcfi_online) { + fcftab->fcfi_online--; + } + } + + /* Check if online was requested */ + if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) { + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_action:%d fcfi_online=%d. " + "Online requested.", + fcfp->fcf_index, + fcftab->fcfi_online); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, + FCF_REASON_REQUESTED, 0, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_action:%d fcfi_online=%d. " + "FCFI offline. Notifying fcftab.", + fcfp->fcf_index, + fcftab->fcfi_online); + + /* Notify FCFTAB */ + rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_OFFLINE, fcfp); + + return (rval); + +} /* emlxs_fcfi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + if (evt != FCF_EVENT_VFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_vfi_online_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1, + fcfp->flag); + return (1); + } + + switch (fcfp->state) { + case FCFI_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " + "Reentering online.", + fcfp->fcf_index, + fcfp->flag, + fcfp->vfi_online); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case FCFI_STATE_VFI_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " + "Online cmpl.", + fcfp->fcf_index, + fcfp->flag, + fcfp->vfi_online); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_evt_action:%d flag=%x vfi_online=%d. " + "Terminated.", + fcfp->fcf_index, + fcfp->flag, + fcfp->vfi_online); + return (0); + } + + return (rval); + +} /* emlxs_fcfi_vfi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_offline_handler(emlxs_port_t *port, FCFIobj_t *fcfp, void *arg1) +{ + uint32_t rval; + + if (!(fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { + return (0); + } + + if (fcfp->vfi_online != 0) { + if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED, + FCF_REASON_REQUESTED, 0, arg1); + } else { + rval = emlxs_fcfi_state(port, fcfp, + FCFI_STATE_VFI_OFFLINE, FCF_REASON_REQUESTED, + 0, arg1); + } + + } else if (fcfp->flag & EMLXS_FCFI_REG) { + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, + FCF_REASON_REQUESTED, 0, arg1); + + } else { + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, + FCF_REASON_REQUESTED, 0, arg1); + } + + return (rval); + +} /* emlxs_fcfi_offline_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval; + VFIobj_t *vfip; + + if (evt != FCF_EVENT_VFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1, + fcfp->flag); + return (1); + } + + vfip = (VFIobj_t *)arg1; + vfip->fcfp = NULL; + + switch (fcfp->state) { + case FCFI_STATE_VFI_ONLINE: + case FCFI_STATE_ONLINE: + if (fcfp->vfi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x " + "vfi_online=%d. Offlining.", + fcfp->fcf_index, + fcfp->flag, fcfp->vfi_online); + + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x " + "vfi_online=%d. Terminated.", + fcfp->fcf_index, + fcfp->flag, fcfp->vfi_online); + } + break; + + case FCFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x vfi_online=%d. " + "Terminated.", + fcfp->fcf_index, + fcfp->flag, fcfp->vfi_online); + break; + + case FCFI_STATE_VFI_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.", + fcfp->fcf_index, + fcfp->flag); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + break; + + case FCFI_STATE_VFI_OFFLINE_CMPL: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x. Offline cmpl.", + fcfp->fcf_index, + fcfp->flag); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_OFFLINE_CMPL, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + if (fcfp->vfi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag=%x " + "vfi_online=%d. Offline requested.", + fcfp->fcf_index, + fcfp->flag, fcfp->vfi_online); + + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_evt_action:%d flag = %x " + "vfi_online=%d. Terminated.", + fcfp->fcf_index, + fcfp->flag, fcfp->vfi_online); + } + return (0); + } + + return (rval); + +} /* emlxs_fcfi_vfi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_online_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval = 0; + + if (evt != FCF_EVENT_FCFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_online_evt_action:%d %s:%s arg=%p. " + "Invalid event type. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_ONLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_evt_action:%d. " + "Online already requested. Terminated.", + fcfp->fcf_index); + return (1); + } + + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_ONLINE_REQ; + + switch (fcfp->state) { + case FCFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_evt_action:%d flag=%x. Initiating online.", + fcfp->fcf_index, + fcfp->flag); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, + FCF_REASON_EVENT, evt, arg1); + break; + + case FCFI_STATE_VFI_OFFLINE: + case FCFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_evt_action:%d flag=%x. Initiating online.", + fcfp->fcf_index, + fcfp->flag); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + break; + + case FCFI_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_evt_action:%d flag=%x. Reentering online.", + fcfp->fcf_index, + fcfp->flag); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_evt_action:%d flag=%x. Terminated.", + fcfp->fcf_index, + fcfp->flag); + break; + } + + return (rval); + +} /* emlxs_fcfi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t i; + uint32_t rval; + VFIobj_t *vfip; + + if (fcfp->state != FCFI_STATE_VFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_vfi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_action:%d. Offline requested.", + fcfp->fcf_index); + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + return (rval); + } + + if (fcfp->vfi_online > 0) { + /* Waking up out after being paused */ + + /* Find first VFI of this FCFI */ + vfip = hba->sli.sli4.VFI_table; + for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { + if (vfip->fcfp == fcfp) { + break; + } + } + + } else { + + /* Find first available VFI */ + vfip = hba->sli.sli4.VFI_table; + for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { + if (vfip->fcfp == NULL) { + vfip->fcfp = fcfp; + break; + } + } + } + + if (i == hba->sli.sli4.VFICount) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_action:%d vfi_online=%d. " + "No VFI found. Offlining.", + fcfp->fcf_index, + fcfp->vfi_online); + + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_action:%d vfi_online=%d. Onlining VFI:%d.", + fcfp->fcf_index, + fcfp->vfi_online, + vfip->VFI); + + rval = emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); + + /* Wait for FCF_EVENT_VFI_ONLINE in return */ + + return (rval); + +} /* emlxs_fcfi_vfi_online_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_online_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + if (fcfp->state != FCFI_STATE_VFI_ONLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_vfi_online_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_online_cmpl_action:%d. Going online.", + fcfp->fcf_index); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcfi_vfi_online_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_offline_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + VFIobj_t *vfip; + uint32_t rval; + int32_t i; + + if (fcfp->state != FCFI_STATE_VFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_action:%d vfi_online=%d. Pausing.", + fcfp->fcf_index, + fcfp->vfi_online); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_PAUSED, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (fcfp->vfi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_action:%d. " + "VFI already offline. Skipping VFI offline.", + fcfp->fcf_index); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + /* Offline VFI's of this FCFI */ + for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) { + vfip = &hba->sli.sli4.VFI_table[i]; + + if ((vfip->fcfp != fcfp) || + (vfip->state == VFI_STATE_OFFLINE) || + (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_action:%d. Offlining VFI:%d", + fcfp->fcf_index, + vfip->VFI); + + (void) emlxs_vfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip); + } + + /* Wait for FCF_EVENT_VFI_OFFLINE in return */ + + return (0); + +} /* emlxs_fcfi_vfi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_paused_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + VFIobj_t *vfip; + int32_t i; + + if (fcfp->state != FCFI_STATE_PAUSED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_paused_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + fcfp->flag &= ~(EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); + + /* Pause all VFI's of this FCFI */ + for (i = (hba->sli.sli4.VFICount-1); i >= 0; i--) { + vfip = &hba->sli.sli4.VFI_table[i]; + + if ((vfip->state == VFI_STATE_OFFLINE) || + (vfip->state == VFI_STATE_PAUSED) || + (vfip->fcfp != fcfp)) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_paused_action:%d vfi_online=%d. Pausing VFI:%d.", + fcfp->fcf_index, + fcfp->vfi_online, + vfip->VFI); + + (void) emlxs_vfi_event(port, FCF_EVENT_VFI_PAUSE, vfip); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_paused_action:%d vfi_online=%d. FCFI paused.", + fcfp->fcf_index, + fcfp->vfi_online); + + return (0); + +} /* emlxs_fcfi_paused_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_vfi_offline_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval = 0; + + if (fcfp->state != FCFI_STATE_VFI_OFFLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_vfi_offline_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if ((fcfp->vfi_online == 0) && + (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. " + "Unregistering.", + fcfp->fcf_index, + fcfp->vfi_online); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_vfi_offline_cmpl_action:%d vfi_online=%d. " + "Terminated.", + fcfp->fcf_index, + fcfp->vfi_online); + } + + return (rval); + +} /* emlxs_fcfi_vfi_offline_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_offline_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (evt != FCF_EVENT_FCFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_offline_evt_action:%d %s:%s arg=%p. " + "Invalid event type. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if ((fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) && + !(fcfp->flag & EMLXS_FCFI_PAUSE_REQ)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_evt_action:%d. Offline already requested. " + "Terminated.", + fcfp->fcf_index); + return (1); + } + + switch (fcfp->state) { + case FCFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_evt_action:%d flag=%x. Already offline. " + "Terminated.", + fcfp->fcf_index, + fcfp->flag); + break; + + /* Wait states */ + case FCFI_STATE_VFI_ONLINE: + case FCFI_STATE_VFI_OFFLINE: + case FCFI_STATE_REG: + case FCFI_STATE_ONLINE: + case FCFI_STATE_PAUSED: + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_evt_action:%d flag=%x. Handling offline.", + fcfp->fcf_index, + fcfp->flag); + + /* Handle offline now */ + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + break; + + /* Transitional states */ + default: + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_offline_evt_action:%d. " + "Invalid state. Terminated.", + fcfp->fcf_index); + break; + } + + return (rval); + +} /* emlxs_fcfi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_pause_evt_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (evt != FCF_EVENT_FCFI_PAUSE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_pause_evt_action:%d %s:%s arg=%p. " + "Invalid event type. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d. Pause already requested. " + "Terminated.", + fcfp->fcf_index); + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d. Offline already requested. " + "Terminated.", + fcfp->fcf_index); + return (1); + } + + switch (fcfp->state) { + case FCFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d flag=%x. Already offline. " + "Terminated.", + fcfp->fcf_index, + fcfp->flag); + break; + + case FCFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d flag=%x. Already paused. " + "Terminated.", + fcfp->fcf_index, + fcfp->flag); + break; + + /* Wait states */ + case FCFI_STATE_VFI_ONLINE: + case FCFI_STATE_VFI_OFFLINE: + case FCFI_STATE_REG: + case FCFI_STATE_ONLINE: + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d flag=%x. Handle pause request.", + fcfp->fcf_index, + fcfp->flag); + + /* Handle offline now */ + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + break; + + /* Transitional states */ + default: + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= (EMLXS_FCFI_OFFLINE_REQ | EMLXS_FCFI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_pause_evt_action:%d. " + "Invalid state. Terminated.", + fcfp->fcf_index); + break; + } + + return (rval); + +} /* emlxs_fcfi_pause_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_unreg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + fcfp->attempts++; + + if (fcfp->state != FCFI_STATE_UNREG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), + arg1, fcfp->attempts); + + return (1); + } + + if ((fcfp->reason == FCF_REASON_SEND_FAILED) || + (fcfp->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_failed_action:%d attempt=%d reason=%x. " + "Unreg cmpl.", + fcfp->fcf_index, + fcfp->attempts, + fcfp->reason); + + fcfp->flag &= ~EMLXS_FCFI_REG; + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL, + FCF_REASON_OP_FAILED, fcfp->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_failed_action:%d attempt=%d. Unregistering.", + fcfp->fcf_index, + arg1, fcfp->attempts); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG, + FCF_REASON_OP_FAILED, fcfp->attempts, arg1); + } + + return (rval); + +} /* emlxs_fcfi_unreg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_reg_failed_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + fcfp->attempts++; + + if (fcfp->state != FCFI_STATE_REG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1, + fcfp->attempts); + + return (1); + } + + if ((fcfp->reason == FCF_REASON_SEND_FAILED) || + (fcfp->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", + fcfp->fcf_index, + fcfp->attempts, + fcfp->reason); + + fcfp->flag &= ~EMLXS_FCFI_REG; + fcfp->flag &= ~EMLXS_FCFI_REQ_MASK; + fcfp->flag |= EMLXS_FCFI_OFFLINE_REQ; + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL, + FCF_REASON_OP_FAILED, fcfp->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_failed_action:%d attempt=%d. Registering.", + fcfp->fcf_index, + fcfp->attempts); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG, + FCF_REASON_OP_FAILED, fcfp->attempts, arg1); + } + + return (rval); + +} /* emlxs_fcfi_reg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + FCFIobj_t *fcfp; + + fcfp = (FCFIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (fcfp->state != FCFI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_mbcmpl:%d state=%s. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_mbcmpl:%d failed. status=%x", + fcfp->fcf_index, + mb4->mbxStatus); + + (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + fcfp->FCFI = mb4->un.varRegFCFI.FCFI; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_mbcmpl:%d Registered. FCFI=%d", + fcfp->fcf_index, + fcfp->FCFI); + + fcfp->flag |= EMLXS_FCFI_REG; + + (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_CMPL, + 0, 0, 0); + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_fcfi_reg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_reg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + + if (fcfp->state != FCFI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_reg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (!(fcfp->flag & EMLXS_FCFI_FCFTAB)) { + fcfp->flag |= EMLXS_FCFI_FCFTAB; + fcftab->fcfi_online++; + } + + if (fcfp->prev_state != FCFI_STATE_REG_FAILED) { + fcfp->attempts = 0; + } + + if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_action:%d attempts=%d. Offline requested.", + fcfp->fcf_index, + fcfp->attempts); + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + return (rval); + } + + if (fcfp->flag & EMLXS_FCFI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_action:%d. Already registered. Skipping reg.", + fcfp->fcf_index); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_action:%d attempts=%d. Sending FCFI_REG.", + fcfp->fcf_index, + fcfp->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->mbox_cmpl = emlxs_fcfi_reg_mbcmpl; + mbq->context = (void *)fcfp; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_REG_FCFI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */ + mb4->un.varRegFCFI.InfoIndex = fcfp->fcf_index; + + mb4->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid; + mb4->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK; + mb4->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL; + mb4->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK; + mb4->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE; + + mb4->un.varRegFCFI.RQId1 = 0xffff; + mb4->un.varRegFCFI.RQId2 = 0xffff; + mb4->un.varRegFCFI.RQId3 = 0xffff; + + if (fcfp->flag & EMLXS_FCFI_VLAN_ID) { + mb4->un.varRegFCFI.vv = 1; + mb4->un.varRegFCFI.vlanTag = fcfp->vlan_id; + } + + /* Ignore the fcf record and force FPMA */ + mb4->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_REG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_fcfi_reg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_reg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (fcfp->state != FCFI_STATE_REG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_reg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_cmpl_action:%d. Offline requested.", + fcfp->fcf_index); + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_reg_cmpl_action:%d attempts=%d. Reg cmpl.", + fcfp->fcf_index, + fcfp->attempts); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_VFI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcfi_reg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + FCFIobj_t *fcfp; + + fcfp = (FCFIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (fcfp->state != FCFI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_mbcmpl:%d state=%s. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_mbcmpl:%d failed. status=%x", + fcfp->fcf_index, + mb4->mbxStatus); + + (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_mbcmpl:%d Unregistered.", + fcfp->fcf_index); + + fcfp->flag &= ~EMLXS_FCFI_REG; + (void) emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_fcfi_unreg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_unreg_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + + if (fcfp->state != FCFI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_unreg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (!(fcfp->flag & EMLXS_FCFI_REG)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_action:%d. Not registered. Skipping unreg.", + fcfp->fcf_index); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (fcfp->prev_state != FCFI_STATE_UNREG_FAILED) { + fcfp->attempts = 0; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_action:%d attempts=%d. Sending FCFI_UNREG.", + fcfp->fcf_index, + fcfp->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->mbox_cmpl = emlxs_fcfi_unreg_mbcmpl; + mbq->context = (void *)fcfp; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_UNREG_FCFI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varUnRegFCFI.FCFI = fcfp->FCFI; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_UNREG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_fcfi_unreg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_unreg_cmpl_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (fcfp->state != FCFI_STATE_UNREG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_unreg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_unreg_cmpl_action:%d attempts=%d. Going offline.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1, + fcfp->attempts); + + rval = emlxs_fcfi_state(port, fcfp, FCFI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_fcfi_unreg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_fcfi_online_action(emlxs_port_t *port, FCFIobj_t *fcfp, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + VFIobj_t *vfip; + uint32_t i; + + if (fcfp->state != FCFI_STATE_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "fcfi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + fcfp->fcf_index, + emlxs_fcfi_state_xlate(fcfp->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + fcfp->flag &= ~EMLXS_FCFI_ONLINE_REQ; + + if (fcfp->flag & EMLXS_FCFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_action:%d attempts=%d. Offline requested.", + fcfp->fcf_index, + fcfp->attempts); + + rval = emlxs_fcfi_offline_handler(port, fcfp, arg1); + return (1); + } + + /* Online remaining VFI's for this FCFI */ + vfip = hba->sli.sli4.VFI_table; + for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip++) { + if (vfip->fcfp != fcfp) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_action:%d vfi_online=%d. Onlining VFI:%d.", + fcfp->fcf_index, + fcfp->vfi_online, + vfip->VFI); + + (void) emlxs_vfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); + } + + if (fcfp->prev_state != FCFI_STATE_ONLINE) { + /* Perform VSAN discovery check when first VFI goes online */ + if (fcfp->vfi_online < FCFI_MAX_VFI_COUNT) { + + /* Perform VSAN Discovery (TBD) */ + /* For now we only need 1 VFI */ + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_action:%d vfi_online=%d. " + "VSAN discovery required.", + fcfp->fcf_index, + fcfp->vfi_online); + } + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi_online_action:%d vfi_online=%d. " + "FCFI online. Notifying fcftab.", + fcfp->fcf_index, + fcfp->vfi_online); + + /* Notify FCFTAB */ + rval = emlxs_fcftab_event(port, FCF_EVENT_FCFI_ONLINE, fcfp); + + return (rval); + +} /* emlxs_fcfi_online_action() */ + + +/*ARGSUSED*/ +static int +emlxs_fcf_configured(emlxs_port_t *port, FCFIobj_t *fcfp) +{ + emlxs_hba_t *hba = HBA; + int i; + uint32_t entry_count; + uint32_t valid_entry; + uint32_t match_found; + uint16_t VLanId; + FCF_RECORD_t *fcfrec = &fcfp->fcf_rec; + uint32_t j; + uint32_t k; + + /* Init the primary flag, we may set it later */ + fcfp->flag &= ~(EMLXS_FCFI_PRIMARY|EMLXS_FCFI_BOOT); + + if (!(hba->flag & FC_FIP_SUPPORTED)) { + if (!hba->sli.sli4.cfgFCOE.length) { + /* Nothing specified, so everything matches */ + /* For nonFIP only use index 0 */ + if (fcfrec->fcf_index == 0) { + return (1); /* success */ + } + return (0); + } + + /* Just check FCMap for now */ + if (bcmp((char *)fcfrec->fc_map, + hba->sli.sli4.cfgFCOE.FCMap, 3) == 0) { + return (1); /* success */ + } + return (0); + } + + /* For FIP mode, the FCF record must match Config Region 23 */ + + entry_count = (hba->sli.sli4.cfgFCF.length * sizeof (uint32_t)) / + sizeof (tlv_fcfconnectentry_t); + valid_entry = 0; + match_found = 0; + + for (i = 0; i < entry_count; i++) { + + if (!hba->sli.sli4.cfgFCF.entry[i].Valid) { + continue; + } + + if (hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) { + valid_entry = 1; + + if (bcmp((char *)fcfrec->fabric_name_identifier, + hba->sli.sli4.cfgFCF.entry[i].FabricName, 8)) { + match_found = 0; + continue; + } + + match_found = 1; + } + + if (hba->sli.sli4.cfgFCF.entry[i].SwitchNameValid) { + valid_entry = 1; + + if (bcmp((char *)fcfrec->switch_name_identifier, + hba->sli.sli4.cfgFCF.entry[i].SwitchName, 8)) { + match_found = 0; + continue; + } + + match_found = 1; + } + + if (hba->sli.sli4.cfgFCF.entry[i].VLanValid) { + valid_entry = 1; + + if (!(fcfp->flag & EMLXS_FCFI_VLAN_ID)) { + match_found = 0; + continue; + } + + VLanId = hba->sli.sli4.cfgFCF.entry[i].VLanId; + j = VLanId / 8; + k = 1 << (VLanId % 8); + + if (!(fcfrec->vlan_bitmap[j] & k)) { + match_found = 0; + continue; + } + + /* Assign requested vlan_id to this FCF */ + fcfp->vlan_id = VLanId; + + match_found = 1; + } + + /* If a match was found */ + if (match_found) { + if (hba->sli.sli4.cfgFCF.entry[i].Primary) { + fcfp->flag |= EMLXS_FCFI_PRIMARY; + } + if (hba->sli.sli4.cfgFCF.entry[i].Boot) { + fcfp->flag |= EMLXS_FCFI_BOOT; + } + return (1); + } + } + + /* If no valid entries found, then allow any fabric */ + if (!valid_entry) { + return (1); + } + + return (0); + +} /* emlxs_fcf_configured() */ + + +static void +emlxs_fcfi_update(emlxs_port_t *port, FCFIobj_t *fcfp, FCF_RECORD_t *fcf_rec, + uint32_t event_tag) +{ + emlxs_hba_t *hba = HBA; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint16_t i; + + bcopy((char *)fcf_rec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t)); + fcfp->fcf_index = fcf_rec->fcf_index; + + /* Clear VLAN info */ + fcfp->vlan_id = 0; + fcfp->flag &= ~EMLXS_FCFI_VLAN_ID; + + /* Check if fcf is a member of a VLAN */ + for (i = 0; i < 4096; i++) { + if (fcf_rec->vlan_bitmap[i / 8] & (1 << (i % 8))) { + /* For now assign the VLAN id of the first VLAN found */ + fcfp->vlan_id = i; + fcfp->flag |= EMLXS_FCFI_VLAN_ID; + break; + } + } + + if (fcf_rec->fcf_available) { + fcfp->flag |= EMLXS_FCFI_AVAILABLE; + } else { + fcfp->flag &= ~EMLXS_FCFI_AVAILABLE; + } + + if (fcf_rec->fcf_valid) { + fcfp->flag |= EMLXS_FCFI_VALID; + } else { + fcfp->flag &= ~EMLXS_FCFI_VALID; + } + + /* Check config region 23 */ + /* Also sets BOOT and PRIMARY cfg bits as needed */ + if (emlxs_fcf_configured(port, fcfp)) { + fcfp->flag |= EMLXS_FCFI_CONFIGURED; + } else { + fcfp->flag &= ~EMLXS_FCFI_CONFIGURED; + } + + /* Set fcfp priority. Used by selection alogithm */ + /* Combination of BOOT:PRIMARY:~fip_priority */ + fcfp->priority = (fcfp->flag & EMLXS_FCFI_BOOT)? 0x200:0; + fcfp->priority |= (fcfp->flag & EMLXS_FCFI_PRIMARY)? 0x100:0; + fcfp->priority |= ~(fcf_rec->fip_priority & 0xff); + + fcfp->event_tag = event_tag; + fcfp->generation = fcftab->generation; + fcfp->flag |= EMLXS_FCFI_FRESH; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi:%d gen=%x tag=%x flag=%x avl=%x val=%x state=%x " + "map=%x pri=%x vid=%x", + fcf_rec->fcf_index, + fcfp->generation, + fcfp->event_tag, + fcfp->flag, + fcf_rec->fcf_available, + fcf_rec->fcf_valid, + fcf_rec->fcf_state, + fcf_rec->mac_address_provider, + fcfp->priority, + fcfp->vlan_id); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "fcfi:%d mac=%02x:%02x:%02x:%02x:%02x:%02x " + "fabric=%02x%02x%02x%02x%02x%02x%02x%02x " + "switch=%02x%02x%02x%02x%02x%02x%02x%02x", + fcfp->fcf_index, + fcf_rec->fcf_mac_address_hi[0], + fcf_rec->fcf_mac_address_hi[1], + fcf_rec->fcf_mac_address_hi[2], + fcf_rec->fcf_mac_address_hi[3], + fcf_rec->fcf_mac_address_low[0], + fcf_rec->fcf_mac_address_low[1], + + fcf_rec->fabric_name_identifier[0], + fcf_rec->fabric_name_identifier[1], + fcf_rec->fabric_name_identifier[2], + fcf_rec->fabric_name_identifier[3], + fcf_rec->fabric_name_identifier[4], + fcf_rec->fabric_name_identifier[5], + fcf_rec->fabric_name_identifier[6], + fcf_rec->fabric_name_identifier[7], + + fcf_rec->switch_name_identifier[0], + fcf_rec->switch_name_identifier[1], + fcf_rec->switch_name_identifier[2], + fcf_rec->switch_name_identifier[3], + fcf_rec->switch_name_identifier[4], + fcf_rec->switch_name_identifier[5], + fcf_rec->switch_name_identifier[6], + fcf_rec->switch_name_identifier[7]); + + return; + +} /* emlxs_fcfi_update() */ + + +/* ************************************************************************** */ +/* VFI */ +/* ************************************************************************** */ + +static char * +emlxs_vfi_state_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_vfi_state_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_vfi_state_table[i].code) { + return (emlxs_vfi_state_table[i].string); + } + } + + (void) sprintf(buffer, "state=0x%x", state); + return (buffer); + +} /* emlxs_vfi_state_xlate() */ + + +static uint32_t +emlxs_vfi_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + uint32_t(*func) (emlxs_port_t *, VFIobj_t *, uint32_t, void *); + uint32_t index; + uint32_t events; + uint16_t state; + + /* Convert event to action table index */ + switch (evt) { + case FCF_EVENT_STATE_ENTER: + index = 0; + break; + case FCF_EVENT_VFI_ONLINE: + index = 1; + break; + case FCF_EVENT_VFI_OFFLINE: + index = 2; + break; + case FCF_EVENT_VFI_PAUSE: + index = 3; + break; + case FCF_EVENT_VPI_ONLINE: + index = 4; + break; + case FCF_EVENT_VPI_OFFLINE: + index = 5; + break; + default: + return (1); + } + + events = VFI_ACTION_EVENTS; + state = vfip->state; + + index += (state * events); + func = (uint32_t(*) (emlxs_port_t *, VFIobj_t *, uint32_t, void *)) + emlxs_vfi_action_table[index]; + + if (!func) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vfi:%d %s:%s arg=%p. No action. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + rval = (func)(port, vfip, evt, arg1); + + return (rval); + +} /* emlxs_vfi_action() */ + + +static uint32_t +emlxs_vfi_event(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + VPIobj_t *vpip = NULL; + VFIobj_t *vfip = NULL; + uint32_t rval = 0; + + /* Filter events and acquire fcfi context */ + switch (evt) { + case FCF_EVENT_VPI_ONLINE: + case FCF_EVENT_VPI_OFFLINE: + vpip = (VPIobj_t *)arg1; + + if (!vpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vfi: %s arg=%p. Null VPI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + vfip = vpip->vfip; + + if (!vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vfi: %s arg=%p. VFI not found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + break; + + case FCF_EVENT_VFI_ONLINE: + case FCF_EVENT_VFI_OFFLINE: + case FCF_EVENT_VFI_PAUSE: + vfip = (VFIobj_t *)arg1; + + if (!vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vfi: %s arg=%p. VFI not found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + break; + + default: + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vfi:%d %s:%s arg=%p", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_vfi_action(port, vfip, evt, arg1); + + return (rval); + +} /* emlxs_vfi_event() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_state(emlxs_port_t *port, VFIobj_t *vfip, uint16_t state, + uint16_t reason, uint32_t explain, void *arg1) +{ + uint32_t rval; + + if (state >= VFI_ACTION_STATES) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_state:%d %s. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state)); + + return (1); + } + + if ((vfip->state == state) && + (reason != FCF_REASON_REENTER)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_state:%d %s:%s:0x%x arg=%p. " + "State not changed. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + + return (1); + } + + if (!reason) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vfi:%d %s-->%s arg=%p", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_vfi_state_xlate(state), arg1); + } else if (reason == FCF_REASON_EVENT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vfi:%d %s-->%s:%s:%s arg=%p", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_vfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + emlxs_fcf_event_xlate(explain), arg1); + } else if (explain) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vfi:%d %s-->%s:%s:0x%x arg=%p", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_vfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vfi:%d %s-->%s:%s arg=%p", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_vfi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), arg1); + } + + vfip->prev_state = vfip->state; + vfip->prev_reason = vfip->reason; + vfip->state = state; + vfip->reason = reason; + + rval = emlxs_vfi_action(port, vfip, FCF_EVENT_STATE_ENTER, arg1); + + return (rval); + +} /* emlxs_vfi_state() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + if (evt != FCF_EVENT_VPI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_vpi_online_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + + return (1); + } + + switch (vfip->state) { + case VFI_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " + "Reentering online.", + vfip->VFI, + vfip->flag, + vfip->vpi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case VFI_STATE_VPI_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " + "Online cmpl.", + vfip->VFI, + vfip->flag, + vfip->vpi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_evt_action:%d flag=%x vpi_online=%d. " + "Terminated.", + vfip->VFI, + vfip->flag, + vfip->vpi_online); + + return (1); + } + + return (rval); + +} /* emlxs_vfi_vpi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_offline_handler(emlxs_port_t *port, VFIobj_t *vfip, void *arg1) +{ + uint32_t rval; + + if (!(vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { + return (0); + } + + if (vfip->vpi_online > 0) { + if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED, + FCF_REASON_REQUESTED, 0, arg1); + } else { + rval = emlxs_vfi_state(port, vfip, + VFI_STATE_VPI_OFFLINE, FCF_REASON_REQUESTED, + 0, arg1); + } + + } else if (vfip->flag & EMLXS_VFI_REG) { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, + FCF_REASON_REQUESTED, 0, arg1); + + } else if (vfip->flag & EMLXS_VFI_INIT) { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, + FCF_REASON_REQUESTED, 0, arg1); + + } else { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, + FCF_REASON_REQUESTED, 0, arg1); + } + + return (rval); + +} /* emlxs_vfi_offline_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + VPIobj_t *vpip; + + if (evt != FCF_EVENT_VPI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + return (1); + } + + /* Disconnect VPI object from VFI */ + vpip = (VPIobj_t *)arg1; + vpip->vfip = NULL; + + switch (vfip->state) { + case VFI_STATE_ONLINE: + case VFI_STATE_VPI_ONLINE: + if (vfip->vpi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x " + "vpi_online=%d. Offlining.", + vfip->VFI, + vfip->flag, vfip->vpi_online); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x " + "vpi_online=%d. Terminated.", + vfip->VFI, + vfip->flag, vfip->vpi_online); + } + break; + + case VFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_vpi_offline_evt_action:%d flag=%x vpi_online=%d. " + "Terminated.", + vfip->VFI, + vfip->flag, vfip->vpi_online); + break; + + case VFI_STATE_VPI_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.", + vfip->VFI, + vfip->flag); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL, + FCF_REASON_EVENT, evt, arg1); + break; + + case VFI_STATE_VPI_OFFLINE_CMPL: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x. VPI offline cmpl.", + vfip->VFI, + vfip->flag); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_OFFLINE_CMPL, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + if (vfip->vpi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x "\ + "vpi_online=%d. Requesting offline.", + vfip->VFI, + vfip->flag, vfip->vpi_online); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_evt_action:%d flag=%x "\ + "vpi_online=%d. Terminated.", + vfip->VFI, + vfip->flag, vfip->vpi_online); + } + return (1); + } + + return (rval); + +} /* emlxs_vfi_vpi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_online_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *vport; + VPIobj_t *vpip; + uint32_t rval = 0; + uint32_t i; + + if (evt != FCF_EVENT_VFI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_online_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + return (1); + } + + if (vfip->flag & EMLXS_VFI_ONLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_evt_action:%d flag=%x. " + "Online already requested. Terminated.", + vfip->VFI, + vfip->flag); + return (0); + } + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_ONLINE_REQ; + + switch (vfip->state) { + case VFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_evt_action:%d flag=%x. Initiating online.", + vfip->VFI, + vfip->flag); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, + FCF_REASON_EVENT, evt, arg1); + break; + + case VFI_STATE_VPI_OFFLINE: + case VFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_evt_action:%d flag=%x. Initiating online.", + vfip->VFI, + vfip->flag); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + break; + + case VFI_STATE_ONLINE: + /* Online all VPI's belonging to this vfi */ + for (i = 0; i <= hba->vpi_max; i++) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if (!(vport->flag & EMLXS_PORT_BOUND)) { + continue; + } + + if (vpip->vfip != vfip) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_evt_action:%d. Onlining VPI:%d", + vfip->VFI, + vpip->VPI); + + (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, + vpip); + } + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_evt_action:%d flag=%x. Terminated.", + vfip->VFI, + vfip->flag); + return (1); + } + + return (rval); + +} /* emlxs_vfi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_offline_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 0; + + if (evt != FCF_EVENT_VFI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_offline_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + return (1); + } + + if ((vfip->flag & EMLXS_VFI_OFFLINE_REQ) && + !(vfip->flag & EMLXS_VFI_PAUSE_REQ)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_evt_action:%d flag=%x. " + "Offline already requested. Terminated.", + vfip->VFI, + vfip->flag); + return (0); + } + + switch (vfip->state) { + case VFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_evt_action:%d flag=%x. " + "Already offline. Terminated.", + vfip->VFI, + vfip->flag); + break; + + /* Wait states */ + case VFI_STATE_VPI_ONLINE: + case VFI_STATE_VPI_OFFLINE: + case VFI_STATE_VPI_OFFLINE_CMPL: + case VFI_STATE_INIT: + case VFI_STATE_REG: + case VFI_STATE_ONLINE: + case VFI_STATE_PAUSED: + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_evt_action:%d flag=%x. Handling offline.", + vfip->VFI, + vfip->flag); + + /* Handle offline now */ + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + break; + + default: + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_evt_action:%d flag=%x. Terminated.", + vfip->VFI, + vfip->flag); + break; + } + + return (rval); + +} /* emlxs_vfi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_pause_evt_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 0; + + if (evt != FCF_EVENT_VFI_PAUSE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_pause_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + return (1); + } + + if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. " + "Pause already requested. Terminated.", + vfip->VFI, + vfip->flag); + return (0); + } + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. " + "Offline already requested. Terminated.", + vfip->VFI, + vfip->flag); + return (0); + } + + switch (vfip->state) { + case VFI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. " + "Already offline. Terminated.", + vfip->VFI, + vfip->flag); + break; + + case VFI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. " + "Already paused. Terminated.", + vfip->VFI, + vfip->flag); + break; + + /* Wait states */ + case VFI_STATE_VPI_ONLINE: + case VFI_STATE_VPI_OFFLINE_CMPL: + case VFI_STATE_INIT: + case VFI_STATE_REG: + case VFI_STATE_ONLINE: + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. Handling offline.", + vfip->VFI, + vfip->flag); + + /* Handle offline now */ + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + break; + + default: + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= (EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_pause_evt_action:%d flag=%x. Terminated.", + vfip->VFI, + vfip->flag); + break; + } + + return (rval); + +} /* emlxs_vfi_pause_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vfip->state != VFI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (!vfip->fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_action:%d %s:%s arg=%p flag=%x. " + "Null fcfp found. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->flag); + return (1); + } + + vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); + + if (vfip->prev_state == VFI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_action:%d vfi_online=%d. Terminated.", + vfip->VFI, + vfip->fcfp->vfi_online); + + return (0); + } + + if (vfip->vpi_online) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_offline_action:%d vpi_online=%d. VPI's still online.", + vfip->VFI, + vfip->vpi_online); + } + + if (vfip->flag & EMLXS_VFI_FCFI) { + vfip->flag &= ~EMLXS_VFI_FCFI; + + if (vfip->fcfp->vfi_online) { + vfip->fcfp->vfi_online--; + } + } + + /* Check if online was requested */ + if (vfip->flag & EMLXS_VFI_ONLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_action:%d vfi_online=%d. Online requested.", + vfip->VFI, + vfip->fcfp->vfi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, + FCF_REASON_REQUESTED, 0, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_offline_action:%d vfi_online=%d. " + "VFI offline. Notifying FCFI:%d", + vfip->VFI, + vfip->fcfp->vfi_online, + vfip->fcfp->fcf_index); + + /* Notify FCFI */ + rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_OFFLINE, vfip); + + return (rval); + +} /* emlxs_vfi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + VFIobj_t *vfip; + MAILBOX4 *mb4; + + vfip = (VFIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vfip->state != VFI_STATE_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_mbcmpl:%d %s. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_mbcmpl:%d failed. status=%x", + vfip->VFI, + mb4->mbxStatus); + + (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_mbcmpl:%d Initialized.", + vfip->VFI, + mb4->mbxStatus); + + vfip->flag |= EMLXS_VFI_INIT; + (void) emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vfi_init_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_init_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOXQ *mbq; + MAILBOX4 *mb4; + uint32_t rval; + + if (vfip->state != VFI_STATE_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (!(vfip->flag & EMLXS_VFI_FCFI)) { + vfip->flag |= EMLXS_VFI_FCFI; + vfip->fcfp->vfi_online++; + } + + if (vfip->prev_state != VFI_STATE_INIT_FAILED) { + vfip->attempts = 0; + } + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d attempts=%d. Offline requested.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + if (vfip->flag & EMLXS_VFI_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d flag=%x. " + "Already init'd. Skipping init.", + vfip->VFI); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vfip->fcfp->vfi_online == 1) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d vfi_online=%d. Skipping init.", + vfip->VFI, + vfip->fcfp->vfi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d vfi_online=%d attempts=%d", + vfip->VFI, + vfip->fcfp->vfi_online, + vfip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vfi_state(port, vfip, FCFI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_vfi_init_mbcmpl; + mbq->context = (void *)vfip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_INIT_VFI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varInitVFI4.fcfi = vfip->fcfp->FCFI; + mb4->un.varInitVFI4.vfi = vfip->VFI; + + /* ??? This function is untested and incomplete */ + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vfi_init_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_init_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vfip->attempts++; + + if (vfip->state != VFI_STATE_INIT_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_init_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->attempts); + + return (1); + } + + if ((vfip->reason == FCF_REASON_SEND_FAILED) || + (vfip->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d attempt=%d reason=%x. Init cmpl.", + vfip->VFI, + vfip->attempts, + vfip->reason); + + vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT_CMPL, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_action:%d attempt=%d. Initializing.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_INIT, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vfi_init_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_init_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vfip->state != VFI_STATE_INIT_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_init_cmpl_action:%d attempts=%d. Init cmpl.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_VPI_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vfi_init_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + uint32_t i; + emlxs_port_t *vport; + VPIobj_t *vpip; + + if (vfip->state != VFI_STATE_VPI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_action:%d. Offline requested.", + vfip->VFI); + + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + if (vfip->logi_count > 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " + "VPI already logged in.", + vfip->VFI, + vfip->vpi_online, + vfip->logi_count); + } + + if (vfip->vpi_online > 0) { + /* Waking up out after being paused */ + + /* Find first VPI of this VFI */ + for (i = 0; i <= hba->vpi_max; i++) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if (!(vport->flag & EMLXS_PORT_BOUND)) { + continue; + } + + if (vpip->vfip == vfip) { + break; + } + } + + } else { + + /* Find first available VPI */ + for (i = 0; i <= hba->vpi_max; i++) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if (!(vport->flag & EMLXS_PORT_BOUND)) { + continue; + } + + if (vpip->vfip == NULL) { + vpip->vfip = vfip; + break; + } + } + } + + if (i > hba->vpi_max) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " + "No VPI found. Offlining.", + vfip->VFI, + vfip->vpi_online, + vfip->logi_count); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_action:%d vpi_online=%d logi_count=%d. " + "Onlining VPI:%d", + vfip->VFI, + vfip->vpi_online, + vfip->logi_count, + vpip->VPI); + + rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip); + + /* Wait for FCF_EVENT_VPI_ONLINE in return */ + + return (rval); + +} /* emlxs_vfi_vpi_online_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_online_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + if (vfip->state != VFI_STATE_VPI_ONLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vfip->vpi_online > 1) { + /* Waking up after pause */ + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d " + "logi_count=%d. Going online.", + vfip->VFI, + vfip->flag, + vfip->vpi_online, + vfip->logi_count); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_online_cmpl_action:%d flag=%x vpi_online=%d " + "logi_count=%d. Registering.", + vfip->VFI, + vfip->flag, + vfip->vpi_online, + vfip->logi_count); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG, + FCF_REASON_EVENT, evt, arg1); + } + + return (rval); + +} /* emlxs_vfi_vpi_online_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_offline_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, + uint32_t evt, void *arg1) +{ + uint32_t rval = 0; + + if (vfip->state != VFI_STATE_VPI_OFFLINE_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if ((vfip->vpi_online == 0) && + (vfip->flag & EMLXS_VFI_OFFLINE_REQ)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. " + "Unregistering.", + vfip->VFI, + vfip->vpi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_cmpl_action:%d vpi_online=%d. Terminated.", + vfip->VFI, + vfip->vpi_online); + } + + return (rval); + +} /* emlxs_vfi_vpi_offline_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_vpi_offline_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *vport; + uint32_t rval; + int32_t i; + VPIobj_t *vpip; + + if (vfip->state != VFI_STATE_VPI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vfip->flag & EMLXS_VFI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_action:%d vpi_online=%d. Pausing.", + vfip->VFI, + vfip->vpi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_PAUSED, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (vfip->vpi_online == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_action:%d vpi_online=%d. " + "VPI already offline. Skipping offline.", + vfip->VFI, + vfip->vpi_online); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + /* Offline all VPI's of this VFI */ + for (i = hba->vpi_max; i >= 0; i--) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if ((vpip->state == VPI_STATE_OFFLINE) || + (vpip->vfip != vfip)) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_vpi_offline_action:%d. Offlining VPI:%d.", + vfip->VFI, + vpip->VPI); + + (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_OFFLINE, vpip); + } + + /* Wait for FCF_EVENT_VPI_OFFLINE in return */ + + return (0); + +} /* emlxs_vfi_vpi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_paused_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *vport; + int32_t i; + VPIobj_t *vpip; + + if (vfip->state != VFI_STATE_PAUSED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_paused_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vfip->flag &= ~(EMLXS_VFI_OFFLINE_REQ | EMLXS_VFI_PAUSE_REQ); + + /* Pause all VPI's of this VFI */ + for (i = hba->vpi_max; i >= 0; i--) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if ((vpip->state == VPI_STATE_PAUSED) || + (vpip->vfip != vfip)) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_paused_action:%d vpi_online=%d. Pausing VPI:%d.", + vfip->VFI, + vfip->vpi_online, + vpip->VPI); + + (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_PAUSE, vpip); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_paused_action:%d vpi_online=%d. VFI paused.", + vfip->VFI, + vfip->vpi_online); + + return (0); + +} /* emlxs_vfi_paused_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_unreg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vfip->attempts++; + + if (vfip->state != VFI_STATE_UNREG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->attempts); + + return (1); + } + + if (vfip->attempts >= 3) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_failed_action:%d attempt=%d. Unreg cmpl.", + vfip->VFI, + vfip->attempts); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_failed_action:%d attempt=%d. Unregistering.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vfi_unreg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + VFIobj_t *vfip; + + vfip = (VFIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vfip->state != VFI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_mbcmpl:%d state=%s. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_mbcmpl:%d failed. status=%x", + vfip->VFI, + mb4->mbxStatus); + + (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_mbcmpl:%d Unregistered.", + vfip->VFI); + + vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); + (void) emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vfi_unreg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_unreg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + + if (vfip->state != VFI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_unreg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (!(vfip->flag & EMLXS_VFI_REG)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_action:%d. Not registered. Skipping unreg.", + vfip->VFI); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vfip->prev_state != VFI_STATE_UNREG_FAILED) { + vfip->attempts = 0; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_action:%d attempts=%d. Sending UNREG_VFI.", + vfip->VFI, + vfip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_vfi_unreg_mbcmpl; + mbq->context = (void *)vfip; + mbq->port = (void *)port; + + mb4->un.varUnRegVFI4.vfi = vfip->VFI; + mb4->mbxCommand = MBX_UNREG_VFI; + mb4->mbxOwner = OWN_HOST; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_UNREG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vfi_unreg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_unreg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vfip->state != VFI_STATE_UNREG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_unreg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_unreg_cmpl_action:%d attempts=%d. Going offline.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vfi_unreg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_reg_failed_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vfip->attempts++; + + if (vfip->state != VFI_STATE_REG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1, + vfip->attempts); + + return (1); + } + + if ((vfip->reason == FCF_REASON_SEND_FAILED) || + (vfip->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", + vfip->VFI, + vfip->attempts, + vfip->reason); + + vfip->flag &= ~(EMLXS_VFI_REG | EMLXS_VFI_INIT); + + vfip->flag &= ~EMLXS_VFI_REQ_MASK; + vfip->flag |= EMLXS_VFI_OFFLINE_REQ; + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_failed_action:%d attempt=%d. Registering.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG, + FCF_REASON_OP_FAILED, vfip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vfi_reg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + VFIobj_t *vfip; + + vfip = (VFIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vfip->state != VFI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_mbcmpl:%d state=%s. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_mbcmpl:%d failed. status=%x", + vfip->VFI, + mb4->mbxStatus); + + (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_mbcmpl:%d Registered.", + vfip->VFI); + + if (vfip->vpi_online == 1) { + port->VPIobj.flag |= EMLXS_VPI_REG; + } + + vfip->flag |= EMLXS_VFI_REG; + + (void) emlxs_vfi_state(port, vfip, VFI_STATE_REG_CMPL, 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vfi_reg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_reg_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + FCFIobj_t *fcfp; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + MATCHMAP *mp; + uint32_t rval; + uint32_t edtov; + uint32_t ratov; + + if (vfip->state != VFI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_reg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (vfip->prev_state != VFI_STATE_REG_FAILED) { + vfip->attempts = 0; + } + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_action:%d %attempts=%d. Offline requested.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + if (vfip->flag & EMLXS_VFI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_action:%d flag=%x. " + "Already registered. Skipping reg.", + vfip->VFI); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vfip->fcf_sparam.cmn.edtovResolution) { + edtov = (LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov) + 999999) / + 1000000; + } else { + edtov = LE_SWAP32(vfip->fcf_sparam.cmn.e_d_tov); + } + + ratov = (LE_SWAP32(vfip->fcf_sparam.cmn.w2.r_a_tov) + 999) / 1000; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_action:%d attempts=%d edtov=%d ratov=%d. " + "Sending REG_VFI.", + vfip->VFI, + vfip->attempts, + edtov, ratov); + + fcfp = vfip->fcfp; + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, + FCF_REASON_NO_BUFFER, 0, arg1); + + return (1); + } + + mbq->bp = (void *)mp; + mbq->nonembed = NULL; + + mbq->mbox_cmpl = emlxs_vfi_reg_mbcmpl; + mbq->context = (void *)vfip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_REG_VFI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varRegVFI4.vfi = vfip->VFI; + + if (vfip->fcfp->vfi_online == 1) { + mb4->un.varRegVFI4.vp = 1; + mb4->un.varRegVFI4.vpi = port->VPIobj.VPI; + } + + mb4->un.varRegVFI4.fcfi = fcfp->FCFI; + mb4->un.varRegVFI4.sid = port->did; + mb4->un.varRegVFI4.edtov = edtov; + + /* Convert to seconds */ + mb4->un.varRegVFI4.ratov = ratov; + mb4->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM); + mb4->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys); + mb4->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys); + bcopy((uint32_t *)&vfip->fcf_sparam, + (uint32_t *)mp->virt, sizeof (SERV_PARM)); + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_REG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vfi_reg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_reg_cmpl_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vfip->state != VFI_STATE_REG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vfi_reg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_cmpl_action:%d attempts=%d. Offline requested.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_reg_cmpl_action:%d attempts=%d. Going online.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_state(port, vfip, VFI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vfi_reg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vfi_online_action(emlxs_port_t *port, VFIobj_t *vfip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t i; + uint32_t rval; + VPIobj_t *vpip; + emlxs_port_t *vport; + + if (vfip->state != VFI_STATE_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vfip->VFI, + emlxs_vfi_state_xlate(vfip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vfip->flag &= ~EMLXS_VFI_ONLINE_REQ; + + if (vfip->flag & EMLXS_VFI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_action:%d attempts=%d. Offline requested.", + vfip->VFI, + vfip->attempts); + + rval = emlxs_vfi_offline_handler(port, vfip, arg1); + return (rval); + } + + vpip = &port->VPIobj; + + /* Take Fabric RPI online now */ + if (vpip->rpip->state != RPI_STATE_ONLINE) { + /* This will complete the FLOGI/FDISC back to Leadville */ + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, vpip->rpip); + } + + /* FLOGI/FDISC has been completed back to Leadville */ + /* It is now safe to accept unsolicited requests */ + vpip->flag |= EMLXS_VPI_PORT_ENABLED; + + /* Online remaining VPI's */ + for (i = 0; i <= hba->vpi_max; i++) { + vport = &VPORT(i); + vpip = &vport->VPIobj; + + if (!(vport->flag & EMLXS_PORT_BOUND)) { + continue; + } + + if ((vpip->state == VPI_STATE_ONLINE) || + (vpip->flag & EMLXS_VPI_ONLINE_REQ)) { + continue; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_action:%d vpi_online=%d logi_count=%d. " + "Onlining VPI:%d", + vfip->VFI, + vfip->vpi_online, + vfip->logi_count, + vpip->VPI); + + vpip->vfip = vfip; + (void) emlxs_vpi_event(vport, FCF_EVENT_VPI_ONLINE, vpip); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vfi_online_action:%d vpi_online=%d logi_count=%d. " + "VFI online. Notifying FCFI:%d.", + vfip->VFI, + vfip->vpi_online, + vfip->logi_count, + vfip->fcfp->fcf_index); + + /* Notify FCFI */ + rval = emlxs_fcfi_event(port, FCF_EVENT_VFI_ONLINE, vfip); + + return (rval); + +} /* emlxs_vfi_online_action() */ + + +/* ************************************************************************** */ +/* VPI */ +/* ************************************************************************** */ + +static char * +emlxs_vpi_state_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_vpi_state_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_vpi_state_table[i].code) { + return (emlxs_vpi_state_table[i].string); + } + } + + (void) sprintf(buffer, "state=0x%x", state); + return (buffer); + +} /* emlxs_vpi_state_xlate() */ + + +static uint32_t +emlxs_vpi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + uint32_t(*func) (emlxs_port_t *, VPIobj_t *, uint32_t, void *); + uint32_t index; + uint32_t events; + uint16_t state; + + /* Convert event to action table index */ + switch (evt) { + case FCF_EVENT_STATE_ENTER: + index = 0; + break; + case FCF_EVENT_VPI_ONLINE: + index = 1; + break; + case FCF_EVENT_VPI_OFFLINE: + index = 2; + break; + case FCF_EVENT_VPI_PAUSE: + index = 3; + break; + case FCF_EVENT_RPI_ONLINE: + index = 4; + break; + case FCF_EVENT_RPI_OFFLINE: + index = 5; + break; + case FCF_EVENT_RPI_PAUSE: + index = 6; + break; + default: + return (1); + } + + events = VPI_ACTION_EVENTS; + state = vpip->state; + + index += (state * events); + func = (uint32_t(*) (emlxs_port_t *, VPIobj_t *, uint32_t, void *)) + emlxs_vpi_action_table[index]; + + if (!func) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vpi:%d %s:%s arg=%p. No action. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + rval = (func)(port, vpip, evt, arg1); + + return (rval); + +} /* emlxs_vpi_action() */ + + +static uint32_t +emlxs_vpi_event(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + VPIobj_t *vpip = NULL; + RPIobj_t *rpip; + uint32_t rval; + + /* Filter events and acquire fcfi context */ + switch (evt) { + case FCF_EVENT_RPI_ONLINE: + case FCF_EVENT_RPI_OFFLINE: + case FCF_EVENT_RPI_PAUSE: + rpip = (RPIobj_t *)arg1; + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "rpi: %s arg=%p. Null RPI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + vpip = rpip->vpip; + break; + + case FCF_EVENT_VPI_ONLINE: + case FCF_EVENT_VPI_PAUSE: + case FCF_EVENT_VPI_OFFLINE: + vpip = (VPIobj_t *)arg1; + + if (!vpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vpi: %s arg=%p. Null VPI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + break; + + default: + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "vpi:%d %s:%s arg=%p", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_vpi_action(port, vpip, evt, arg1); + + return (rval); + +} /* emlxs_vpi_event() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_state(emlxs_port_t *port, VPIobj_t *vpip, uint16_t state, + uint16_t reason, uint32_t explain, void *arg1) +{ + uint32_t rval = 0; + + if (state >= VPI_ACTION_STATES) { + return (1); + } + + if ((vpip->state == state) && + (reason != FCF_REASON_REENTER)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_state:%d %s:%s:0x%x arg=%p. " + "State not changed. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + + return (1); + } + + if (!reason) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vpi:%d %s-->%s arg=%p", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_vpi_state_xlate(state), arg1); + } else if (reason == FCF_REASON_EVENT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vpi:%d %s-->%s:%s:%s arg=%p", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_vpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + emlxs_fcf_event_xlate(explain), arg1); + } else if (explain) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vpi:%d %s-->%s:%s:0x%x arg=%p", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_vpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "vpi:%d %s-->%s:%s arg=%p", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_vpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), arg1); + } + + vpip->prev_state = vpip->state; + vpip->prev_reason = vpip->reason; + vpip->state = state; + vpip->reason = reason; + + rval = emlxs_vpi_action(port, vpip, FCF_EVENT_STATE_ENTER, arg1); + + return (rval); + +} /* emlxs_vpi_state() */ + + +extern uint32_t +emlxs_vpi_port_bind_notify(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + VPIobj_t *vpip = &port->VPIobj; + FCFTable_t *fcftab = &hba->sli.sli4.fcftab; + uint32_t rval = 0; + VFIobj_t *vfip; + VFIobj_t *vfip1; + uint32_t i; + FCFIobj_t *fcfp; + FCFIobj_t *fcfp1; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (hba->state < FC_LINK_UP) { + if (port->vpi == 0) { + (void) emlxs_reset_link(hba, 1, 0); + } + return (0); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->vfip) { + vfip = vpip->vfip; + fcfp = vfip->fcfp; + goto done; + } + + /* We need to select a VFI for this VPI */ + + /* First find a selected Fabric */ + fcfp = NULL; + for (i = 0; i < fcftab->fcfi_count; i++) { + fcfp1 = fcftab->fcfi[i]; + + if (fcfp1->flag & EMLXS_FCFI_SELECTED) { + fcfp = fcfp1; + break; + } + } + + if (!fcfp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_bind_notify:%d %s. " + "No FCF available yet. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + /* Find first available VFI for this FCFI */ + vfip = NULL; + vfip1 = hba->sli.sli4.VFI_table; + for (i = 0; i < hba->sli.sli4.VFICount; i++, vfip1++) { + if (vfip1->fcfp == fcfp) { + vfip = vfip1; + break; + } + } + + if (!vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_bind_notify:%d %s fcfi:%d. " + "No VFI available yet. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + fcfp->fcf_index); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + vpip->vfip = vfip; +done: + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_bind_notify:%d %s fcfi:%d vfi:%d. Onlining VPI:%d", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + fcfp->fcf_index, + vfip->VFI, + vpip->VPI); + + rval = emlxs_vpi_event(port, FCF_EVENT_VPI_ONLINE, vpip); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_vpi_port_bind_notify() */ + + +extern uint32_t +emlxs_vpi_port_unbind_notify(emlxs_port_t *port, uint32_t wait) +{ + emlxs_hba_t *hba = HBA; + VPIobj_t *vpip = &port->VPIobj; + uint32_t rval = 0; + VFIobj_t *vfip; + uint32_t i; + FCFIobj_t *fcfp; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state == VPI_STATE_OFFLINE) { + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + vfip = vpip->vfip; + fcfp = vfip->fcfp; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d. " + "Offlining VPI:%d,%d", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + fcfp->fcf_index, + vfip->VFI, + vpip->index, vpip->VPI); + + rval = emlxs_vpi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); + + if (wait && (rval == 0)) { + /* Wait for VPI to go offline */ + i = 0; + while (i++ < 120) { + if (vpip->state == VPI_STATE_OFFLINE) { + break; + } + + mutex_exit(&EMLXS_FCF_LOCK); + DELAYMS(1000); + mutex_enter(&EMLXS_FCF_LOCK); + } + + if (i >= 120) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_port_unbind_notify:%d %s fcfi:%d vfi:%d " + "rpi_online=%d,%d. Offline timeout.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + fcfp->fcf_index, + vfip->VFI, + vpip->rpi_online, vpip->rpi_paused); + } + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_vpi_port_unbind_notify() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_rpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + RPIobj_t *rpip = (RPIobj_t *)arg1; + + if (evt != FCF_EVENT_RPI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_rpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + switch (vpip->state) { + case VPI_STATE_LOGO: + /* rpi_online will be checked when LOGO is complete */ + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. Waiting for LOGO. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 0; + break; + + case VPI_STATE_PORT_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case VPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. VPI paused. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 0; + break; + + case VPI_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 0; + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_offline_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. " + "Invalid state. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 1; + break; + } + + return (rval); + +} /* emlxs_vpi_rpi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_rpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + RPIobj_t *rpip = (RPIobj_t *)arg1; + + if (evt != FCF_EVENT_RPI_PAUSE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + switch (vpip->state) { + case VPI_STATE_LOGO: + /* rpi_online will be checked when LOGO is complete */ + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. Waiting for LOGO. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 0; + break; + + case VPI_STATE_PORT_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_REENTER, 0, 0); + break; + + case VPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. VPI already paused. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 0; + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_pause_evt_action:%d rpi_online=%d,%d did=%x " + "rpi=%d. " + "Invalid state. Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + rval = 1; + break; + } + + return (rval); + +} /* emlxs_vpi_rpi_pause_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_rpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, + uint32_t evt, void *arg1) +{ + RPIobj_t *rpip = (RPIobj_t *)arg1; + + if (evt != FCF_EVENT_RPI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_rpi_online_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_rpi_online_evt_action:%d rpi_online=%d,%d did=%x rpi=%d. " + "Terminated.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->did, rpip->RPI); + + return (0); + +} /* emlxs_vpi_rpi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_online_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (evt != FCF_EVENT_VPI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_online_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + if (vpip->flag & EMLXS_VPI_ONLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_evt_action:%d flag=%x. " + "Online already requested. Terminated.", + vpip->VPI, + vpip->flag); + return (1); + } + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_ONLINE_REQ; + + switch (vpip->state) { + case VPI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_evt_action:%d flag=%x. Initiating online.", + vpip->VPI, + vpip->flag); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, + FCF_REASON_EVENT, evt, arg1); + break; + + case VPI_STATE_PORT_OFFLINE: + case VPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_evt_action:%d flag=%x. Initiating online.", + vpip->VPI, + vpip->flag); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, + FCF_REASON_EVENT, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_evt_action:%d flag=%x. Terminated.", + vpip->VPI, + vpip->flag); + return (1); + } + + return (rval); + +} /* emlxs_vpi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_offline_handler(emlxs_port_t *port, VPIobj_t *vpip, void *arg1) +{ + uint32_t rval; + + if (!(vpip->flag & EMLXS_VPI_OFFLINE_REQ)) { + return (0); + } + + if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_REQUESTED, 0, arg1); + + } else if (vpip->flag & EMLXS_VPI_LOGI) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, + FCF_REASON_REQUESTED, 0, arg1); + + } else if (vpip->flag & EMLXS_VPI_REG) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, + FCF_REASON_REQUESTED, 0, arg1); + + } else if (vpip->flag & EMLXS_VPI_INIT) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, + FCF_REASON_REQUESTED, 0, arg1); + + } else { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, + FCF_REASON_REQUESTED, 0, arg1); + } + + return (rval); + +} /* emlxs_vpi_offline_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_offline_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + uint32_t pause_req; + + if (evt != FCF_EVENT_VPI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_offline_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + if ((vpip->flag & EMLXS_VPI_OFFLINE_REQ) && + !(vpip->flag & EMLXS_VPI_PAUSE_REQ)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. " + "Offline already requested. Terminated.", + vpip->VPI, + vpip->flag); + return (1); + } + + pause_req = vpip->flag & EMLXS_VPI_PAUSE_REQ; + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + + switch (vpip->state) { + case VPI_STATE_PORT_OFFLINE: + if (pause_req || vpip->rpi_paused) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Clear nodes.", + vpip->VPI, + vpip->flag); + + vpip->flag |= EMLXS_VPI_PORT_ONLINE; + + rval = emlxs_vpi_state(port, vpip, + VPI_STATE_PORT_OFFLINE, FCF_REASON_REENTER, evt, + arg1); + + break; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Handling offline.", + vpip->VPI, + vpip->flag); + + /* Handle offline now */ + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + break; + + case VPI_STATE_PAUSED: + if (vpip->rpi_paused) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Clear nodes.", + vpip->VPI, + vpip->flag); + + vpip->flag |= EMLXS_VPI_PORT_ONLINE; + + rval = emlxs_vpi_state(port, vpip, + VPI_STATE_PORT_OFFLINE, FCF_REASON_EVENT, evt, + arg1); + + break; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Handling offline.", + vpip->VPI, + vpip->flag); + + /* Handle offline now */ + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + break; + + /* wait states */ + case VPI_STATE_UNREG: + case VPI_STATE_PORT_ONLINE: + case VPI_STATE_LOGI: + case VPI_STATE_INIT: + case VPI_STATE_REG: + case VPI_STATE_ONLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Handling offline.", + vpip->VPI, + vpip->flag); + + /* Handle offline now */ + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + break; + + /* Transitional states */ + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_evt_action:%d flag=%x. Terminated.", + vpip->VPI, + vpip->flag); + break; + } + + return (rval); + +} /* emlxs_vpi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_pause_evt_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (evt != FCF_EVENT_VPI_PAUSE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. " + "Pause already requested. Terminated.", + vpip->VPI, + vpip->flag); + return (1); + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. " + "Offline already requested. Terminated.", + vpip->VPI, + vpip->flag); + return (1); + } + + if (!(hba->sli.sli4.flag & EMLXS_SLI4_DOWN_LINK)) { + /* Fabric logo is implied */ + vpip->flag &= ~EMLXS_VPI_LOGI; + if (vpip->flag & EMLXS_VPI_VFI_LOGI) { + vpip->flag &= ~EMLXS_VPI_VFI_LOGI; + + if (vpip->vfip->logi_count > 0) { + vpip->vfip->logi_count--; + } + } + } + + switch (vpip->state) { + case VPI_STATE_PORT_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. " + "Already offline. Terminated.", + vpip->VPI, + vpip->flag); + break; + + case VPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. " + "Already paused. Terminated.", + vpip->VPI, + vpip->flag); + break; + + /* Wait states */ + case VPI_STATE_UNREG: + case VPI_STATE_PORT_ONLINE: + case VPI_STATE_LOGI: + case VPI_STATE_INIT: + case VPI_STATE_REG: + case VPI_STATE_ONLINE: + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. Handling offline.", + vpip->VPI, + vpip->flag); + + /* Handle offline now */ + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + break; + + /* Transitional states */ + default: + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= (EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_pause_evt_action:%d flag=%x. Terminated.", + vpip->VPI, + vpip->flag); + break; + } + + return (rval); + +} /* emlxs_vpi_pause_evt_action() */ + + +/* ARGSUSED */ +static void +emlxs_pkt_cmpl_thread(emlxs_hba_t *hba, + void *arg1, void *arg2) +{ + emlxs_buf_t *sbp = (emlxs_buf_t *)arg1; + emlxs_pkt_complete(sbp, -1, 0, 1); + + return; + +} /* emlxs_pkt_cmpl_thread() */ + + +/* ARGSUSED */ +static void +emlxs_port_offline_thread(emlxs_hba_t *hba, + void *arg1, void *arg2) +{ + emlxs_port_t *port = (emlxs_port_t *)arg1; + uint32_t scope = (uint32_t)((uintptr_t)arg2); + + (void) emlxs_port_offline(port, scope); + return; + +} /* emlxs_port_offline_thread() */ + + +/* ARGSUSED */ +static void +emlxs_port_online_thread(emlxs_hba_t *hba, + void *arg1, void *arg2) +{ + emlxs_port_t *port = (emlxs_port_t *)arg1; + + (void) emlxs_port_online(port); + return; + +} /* emlxs_port_online_thread() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_port_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval = 0; + uint32_t scope; + + if (vpip->state != VPI_STATE_PORT_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d flag=%x. Offline port.", + vpip->VPI, + vpip->flag); + + vpip->flag &= ~(EMLXS_VPI_PORT_ONLINE|EMLXS_VPI_PORT_ENABLED); + + if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { + scope = 0xFFFFFFFF; /* Clear all non-FCP2 nodes */ + /* Pause FCP2 nodes */ + } else { + scope = 0xFDFFFFFF; /* Clear all nodes */ + } + + emlxs_thread_spawn(hba, emlxs_port_offline_thread, + (void *)vpip->port, (void *)((uintptr_t)scope)); + + if (vpip->flag & EMLXS_VPI_LOGI) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + } + + if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { + if (vpip->rpi_online > vpip->rpi_paused) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d rpi_online=%d,%d. " + "Pausing. Waiting for RPI's.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + return (0); + } + + /* Take the Fabric RPI offline now */ + if (vpip->rpip->state != RPI_STATE_FREE) { + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, + vpip->rpip); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d rpi_online=%d,%d. Pausing.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (vpip->rpi_online > 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. " + "Waiting for RPI's.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + return (0); + } + + /* Take the Fabric RPI offline now */ + if (vpip->rpip->state != RPI_STATE_FREE) { + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_offline_action:%d rpi_online=%d,%d. Offlining. " + "Unreg VPI.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_port_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_paused_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + if (vpip->state != VPI_STATE_PAUSED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_paused_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_paused_action:%d rpi_online=%d,%d. VPI paused.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + return (0); + +} /* emlxs_vpi_paused_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_offline_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (!vpip->vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_action:%d %s:%s arg=%p flag=%x. " + "Null vfip found. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->flag); + return (1); + } + + /* Take the Fabric RPI offline, if still active */ + if (vpip->rpip->state != RPI_STATE_FREE) { + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, vpip->rpip); + } + + vpip->flag &= ~(EMLXS_VPI_OFFLINE_REQ | EMLXS_VPI_PAUSE_REQ); + + if (vpip->flag & EMLXS_VPI_VFI) { + vpip->flag &= ~EMLXS_VPI_VFI; + + if (vpip->vfip->vpi_online) { + vpip->vfip->vpi_online--; + } + } + + /* Check if online was requested */ + if (vpip->flag & EMLXS_VPI_ONLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_action:%d vpi_online=%d. Online requested.", + vpip->VPI, + vpip->vfip->vpi_online); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, + FCF_REASON_REQUESTED, 0, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_offline_action:%d vpi_online=%d. " + "VPI offline. Notifying VFI:%d.", + vpip->VPI, + vpip->vfip->vpi_online, + vpip->vfip->VFI); + + /* Notify VFI */ + rval = emlxs_vfi_event(port, FCF_EVENT_VPI_OFFLINE, vpip); + + return (rval); + +} /* emlxs_vpi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_init_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + VPIobj_t *vpip; + MAILBOX4 *mb4; + + vpip = (VPIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state != VPI_STATE_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_mbcmpl:%d %s. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_mbcmpl:%d failed. status=%x", + vpip->VPI, + mb4->mbxStatus); + + (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_mbcmpl:%d Initialized.", + vpip->VPI, + mb4->mbxStatus); + + vpip->flag |= EMLXS_VPI_INIT; + (void) emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vpi_init_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_init_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOXQ *mbq; + MAILBOX4 *mb4; + uint32_t rval; + + if (vpip->state != VPI_STATE_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->prev_state != VPI_STATE_INIT_FAILED) { + vpip->attempts = 0; + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d attempts=%d. Offline requested.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + return (rval); + } + + if (!(vpip->flag & EMLXS_VPI_VFI)) { + vpip->flag |= EMLXS_VPI_VFI; + vpip->vfip->vpi_online++; + } + + if (vpip->vfip->vpi_online == 1) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d vpi_online=%d. Skipping init.", + vpip->VPI, + vpip->vfip->vpi_online); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vpip->flag & EMLXS_VPI_INIT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d flag=%x. " + "Already init'd. Skipping init.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d vpi_online=%d attempts=%d. Sending INIT_VPI.", + vpip->VPI, + vpip->vfip->vpi_online, + vpip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vpi_state(port, vpip, FCFI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_vpi_init_mbcmpl; + mbq->context = (void *)vpip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_INIT_VPI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varInitVPI4.vfi = vpip->vfip->VFI; + mb4->un.varInitVPI4.vpi = vpip->VPI; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vpi_init_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_init_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vpip->attempts++; + + if (vpip->state != VPI_STATE_INIT_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_init_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->attempts); + + return (1); + } + + if ((vpip->reason == FCF_REASON_SEND_FAILED) || + (vpip->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d attempt=%d reason=%x. Init cmpl.", + vpip->VPI, + vpip->attempts, + vpip->reason); + + vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT_CMPL, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_action:%d attempt=%d. Initializing.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_INIT, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vpi_init_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_init_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_INIT_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_init_cmpl_action:%d attempts=%d. Onlining port.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_ONLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + +} /* emlxs_vpi_init_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_port_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (vpip->state != VPI_STATE_PORT_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->flag & EMLXS_VPI_PORT_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_online_action:%d. Port already online.", + vpip->VPI); + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_online_action:%d. Offline requested.", + vpip->VPI); + + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + return (rval); + } + + /* Initialize the Fabric RPI */ + if (vpip->rpip->state == RPI_STATE_FREE) { + (void) emlxs_rpi_alloc(port, FABRIC_DID); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_port_online_action:%d vpi_online=%d. Onlining port.", + vpip->VPI, + vpip->vfip->vpi_online); + + /* Notify ULP */ + vpip->flag |= EMLXS_VPI_PORT_ONLINE; + + emlxs_thread_spawn(hba, emlxs_port_online_thread, + (void *)vpip->port, 0); + + /* Wait for emlxs_vpi_logi_notify() */ + + return (0); + +} /* emlxs_vpi_port_online_action() */ + + +extern uint32_t +emlxs_vpi_logi_notify(emlxs_port_t *port, emlxs_buf_t *sbp) +{ + VPIobj_t *vpip = &port->VPIobj; + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state == VPI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "port_logi_notify:%d %s. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (1); + } + + if (vpip->state != VPI_STATE_PORT_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "port_logi_notify:%d %s. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (1); + } + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI, + 0, 0, sbp); + + if (rval) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "port_logi_notify:%d %s rval=%d.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + rval); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_vpi_logi_notify() */ + + +extern uint32_t +emlxs_vpi_logi_cmpl_notify(emlxs_port_t *port, emlxs_buf_t *sbp) +{ + VPIobj_t *vpip = &port->VPIobj; + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, + IOERR_NO_RESOURCES, 1); + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state != VPI_STATE_LOGI) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "port_logi_cmpl_notify:%d %s. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_CMPL, + 0, 0, sbp); + + if (rval) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "port_logi_cmpl_notify:%d %s rval=%d.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + rval); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_vpi_logi_cmpl_notify() */ + + +extern uint32_t +emlxs_vpi_logi_failed_notify(emlxs_port_t *port) +{ + emlxs_hba_t *hba = HBA; + VPIobj_t *vpip = &port->VPIobj; + uint32_t rval; + + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state != VPI_STATE_LOGI) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "port_logi_failed_notify:%d %s. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (1); + } + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGI_FAILED, + FCF_REASON_OP_FAILED, 1, 0); + + if (rval) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "port_logi_failed_notify:%d %s rval=%d.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + rval); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_vpi_logi_failed_notify() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logi_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_buf_t *sbp = (emlxs_buf_t *)arg1; + fc_packet_t *pkt = PRIV2PKT(sbp); + uint32_t rval; + + if (vpip->state != VPI_STATE_LOGI) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_action:%d. Offline requested.", + vpip->VPI); + + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + return (rval); + } + + if (vpip->flag & EMLXS_VPI_LOGI) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_logi_action:%d flag=%x. LOGI already set.", + vpip->VPI); + + vpip->flag &= ~EMLXS_VPI_LOGI; + if (vpip->flag & EMLXS_VPI_VFI_LOGI) { + vpip->flag &= ~EMLXS_VPI_VFI_LOGI; + + if (vpip->vfip->logi_count > 0) { + vpip->vfip->logi_count--; + } + } + } + + /* Set login command based on vfi logi_count */ + if (vpip->vfip->logi_count == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_action:%d logi_count=%d. FLOGI set.", + vpip->VPI, + vpip->vfip->logi_count); + + *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FLOGI; + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_action:%d logi_count=%d. FDISC set.", + vpip->VPI, + vpip->vfip->logi_count); + + *((uint32_t *)pkt->pkt_cmd) = (uint32_t)ELS_CMD_FDISC; + } + + vpip->vfip->logi_count++; + vpip->flag |= EMLXS_VPI_VFI_LOGI; + + return (0); + +} /* emlxs_vpi_logi_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logi_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_LOGI_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_failed_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vpip->flag &= ~EMLXS_VPI_LOGI; + if (vpip->flag & EMLXS_VPI_VFI_LOGI) { + vpip->flag &= ~EMLXS_VPI_VFI_LOGI; + + if (vpip->vfip->logi_count > 0) { + vpip->vfip->logi_count--; + } + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_failed_action:%d. Requesting offline.", + vpip->VPI); + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + + return (rval); + +} /* emlxs_vpi_logi_failed_action() */ + + +static void +emlxs_vpi_flogi_cmpl(emlxs_port_t *port, VPIobj_t *vpip, uint32_t status) +{ + emlxs_hba_t *hba = HBA; + emlxs_buf_t *sbp; + + sbp = vpip->flogi_sbp; + if (!sbp) { + return; + } + vpip->flogi_sbp = NULL; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_flogi_cmpl:%d. status=%x", + vpip->VPI, + status); + + sbp->pkt_flags &= ~PACKET_STATE_VALID; + + if (status) { + emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, + IOERR_NO_RESOURCES, 1); + } else { + emlxs_set_pkt_state(sbp, IOSTAT_SUCCESS, 0, 1); + } + + emlxs_thread_spawn(hba, emlxs_pkt_cmpl_thread, (void *)sbp, 0); + + return; + +} /* emlxs_vpi_flogi_cmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logi_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + SERV_PARM *sp; + fc_packet_t *pkt; + emlxs_buf_t *sbp; + char buffer1[64]; + char buffer2[64]; + + if (vpip->state != VPI_STATE_LOGI_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vpip->flag |= EMLXS_VPI_LOGI; + + sbp = (emlxs_buf_t *)arg1; + if (!sbp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_logi_cmpl_action:%d. Null sbp. Terminated.", + vpip->VPI); + return (1); + } + + /* Check login parameters */ + pkt = PRIV2PKT(sbp); + sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t)); + + /* For safety */ + if (vpip->flogi_sbp) { + emlxs_vpi_flogi_cmpl(port, vpip, 1); + } + vpip->flogi_sbp = sbp; + + /* Update the Fabric RPI */ + bcopy((void *)sp, (void *)&vpip->rpip->sparam, sizeof (SERV_PARM)); + + if (vpip->vfip->vpi_online == 1) { + bcopy((void *)sp, (void *)&vpip->vfip->fcf_sparam, + sizeof (SERV_PARM)); + } + + if (port->prev_did && + ((port->prev_did != port->did) || + bcmp(&port->prev_fabric_sparam.portName, + &port->fabric_sparam.portName, 8)) && + emlxs_nport_count(port)) { + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_cmpl_action:%d. " + "New fabric. Offlining port.", + vpip->VPI); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_cmpl_action: prev_wwpn=%s wwpn=%s prev_did=%x " + "did=%x.", + emlxs_wwn_xlate(buffer1, + (uint8_t *)&port->prev_fabric_sparam.portName), + emlxs_wwn_xlate(buffer2, + (uint8_t *)&port->fabric_sparam.portName), + port->prev_did, port->did); + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logi_cmpl_action:%d. Registering.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_logi_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logo_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + + vpip->attempts++; + + if (vpip->state != VPI_STATE_LOGO_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_logo_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->attempts); + + return (1); + } + + if (hba->state <= FC_LINK_DOWN) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } else if (vpip->attempts >= 3) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_failed_action:%d attempt=%d. Logo cmpl.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_failed_action:%d attempt=%d. Logging out.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vpi_logo_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logo_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + emlxs_port_t *vport = vpip->port; + uint32_t rval; + uint32_t did; + uint32_t sid; + fc_packet_t *pkt; + ELS_PKT *els; + + if (vpip->state != VPI_STATE_LOGO) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_logo_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (!(vpip->flag & EMLXS_VPI_LOGI)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_action:%d. No login. Skipping logo.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (!(hba->flag & FC_ONLINE_MODE)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_action:%d. HBA offline. Skipping logo.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vpip->prev_state != VPI_STATE_LOGO_FAILED) { + vpip->attempts = 0; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_action:%d. Sending logo. Sending LOGO.", + vpip->VPI, + vpip->attempts); + + pkt = emlxs_pkt_alloc(vport, + (sizeof (uint32_t) + sizeof (LOGO)), + (sizeof (uint32_t) + sizeof (LOGO)), 0, KM_NOSLEEP); + + if (!pkt) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED, + FCF_REASON_NO_PKT, 0, arg1); + + return (rval); + } + + pkt->pkt_tran_type = FC_PKT_EXCHANGE; + pkt->pkt_timeout = (2 * hba->fc_ratov); + + /* Build the fc header */ + did = FABRIC_DID; + sid = (vport->did)? vport->did:vport->prev_did; + + pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did); + pkt->pkt_cmd_fhdr.r_ctl = + R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; + pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(sid); + pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; + pkt->pkt_cmd_fhdr.f_ctl = + F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; + pkt->pkt_cmd_fhdr.seq_id = 0; + pkt->pkt_cmd_fhdr.df_ctl = 0; + pkt->pkt_cmd_fhdr.seq_cnt = 0; + pkt->pkt_cmd_fhdr.ox_id = 0xffff; + pkt->pkt_cmd_fhdr.rx_id = 0xffff; + pkt->pkt_cmd_fhdr.ro = 0; + + /* Build the command */ + els = (ELS_PKT *)pkt->pkt_cmd; + els->elsCode = 0x05; + els->un.logo.un.nPortId32 = pkt->pkt_cmd_fhdr.s_id; + bcopy((uint8_t *)&vport->wwpn, + (uint8_t *)&els->un.logo.portName, 8); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_action:%d LOGO:sid=%x did=%x.", + vpip->VPI, + sid, did); + + /* Send the pkt now */ + rval = emlxs_pkt_send(pkt, 1); + if (rval != FC_SUCCESS) { + /* Free the pkt */ + emlxs_pkt_free(pkt); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + /* For now we will send and forget */ + rval = emlxs_vpi_state(port, vpip, VPI_STATE_LOGO_CMPL, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_logo_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_logo_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_LOGO_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_logo_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vpip->flag &= ~EMLXS_VPI_LOGI; + if (vpip->flag & EMLXS_VPI_VFI_LOGI) { + vpip->flag &= ~EMLXS_VPI_VFI_LOGI; + + if (vpip->vfip->logi_count > 0) { + vpip->vfip->logi_count--; + } + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_logo_cmpl_action:%d attempts=%d. Offline RPI's.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_logo_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_unreg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vpip->attempts++; + + if (vpip->state != VPI_STATE_UNREG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->attempts); + + return (1); + } + + if ((vpip->reason == FCF_REASON_SEND_FAILED) || + (vpip->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_failed_action:%d attempt=%d. Unreg cmpl.", + vpip->VPI, + vpip->attempts); + + vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_failed_action:%d attempt=%d. Unregistering.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vpi_unreg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + VPIobj_t *vpip; + + vpip = (VPIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state != VPI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_mbcmpl:%d state=%s. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_mbcmpl:%d failed. status=%x", + vpip->VPI, + mb4->mbxStatus); + + (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_mbcmpl:%d Unregistered.", + vpip->VPI); + + vpip->flag &= ~(EMLXS_VPI_REG | EMLXS_VPI_INIT); + (void) emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_CMPL, 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vpi_unreg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_unreg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + + if (vpip->state != VPI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_unreg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if ((vpip->rpi_online > 0) || + (vpip->rpip->state != RPI_STATE_FREE)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_action:%d rpi_online=%d,%d. Waiting for RPI's.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PORT_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (!(vpip->flag & EMLXS_VPI_REG)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_action:%d. Not registered. Skipping unreg.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vpip->flag & EMLXS_VPI_PAUSE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_action:%d rpi_online=%d,%d. Pausing.", + vpip->VPI, + vpip->rpi_online, vpip->rpi_paused); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_PAUSED, + FCF_REASON_EVENT, evt, arg1); + return (rval); + } + + if (vpip->prev_state != VPI_STATE_UNREG_FAILED) { + vpip->attempts = 0; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_action:%d attempts=%d. Sending UNREG_VPI.", + vpip->VPI, + vpip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_vpi_unreg_mbcmpl; + mbq->context = (void *)vpip; + mbq->port = (void *)vpip->port; + + mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */ + mb4->un.varUnRegVPI4.index = vpip->VPI; + mb4->mbxCommand = MBX_UNREG_VPI; + mb4->mbxOwner = OWN_HOST; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_UNREG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vpi_unreg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_unreg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_UNREG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_unreg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_unreg_cmpl_action:%d attempts=%d. Going offline.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_unreg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_reg_failed_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + vpip->attempts++; + + if (vpip->state != VPI_STATE_REG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1, + vpip->attempts); + return (1); + } + + if ((vpip->reason == FCF_REASON_SEND_FAILED) || + (vpip->attempts >= 3)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_failed_action:%d attempt=%d reason=%x. Reg cmpl.", + vpip->VPI, + vpip->attempts, + vpip->reason); + + vpip->flag &= ~EMLXS_VPI_REQ_MASK; + vpip->flag |= EMLXS_VPI_OFFLINE_REQ; + rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_failed_action:%d attempt=%d. Registering.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG, + FCF_REASON_OP_FAILED, vpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_vpi_reg_failed_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + VPIobj_t *vpip; + + vpip = (VPIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + mutex_enter(&EMLXS_FCF_LOCK); + + if (vpip->state != VPI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_mbcmpl:%d state=%s. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_mbcmpl:%d failed. status=%x", + vpip->VPI, + mb4->mbxStatus); + + (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_mbcmpl:%d. Registered.", + vpip->VPI); + + vpip->flag |= EMLXS_VPI_REG; + (void) emlxs_vpi_state(port, vpip, VPI_STATE_REG_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_vpi_reg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_reg_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t *wwpn; + MAILBOX *mb; + MAILBOXQ *mbq; + uint32_t rval; + + if (vpip->state != VPI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_reg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->prev_state != VPI_STATE_REG_FAILED) { + vpip->attempts = 0; + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_action:%d attempts=%d. Offline requested.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_offline_handler(port, vpip, 0); + return (rval); + } + + if (!(vpip->flag & EMLXS_VPI_REG) && + (vpip->vfip->vpi_online == 1)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_action:%d. First vpi. Skipping reg.", + vpip->VPI); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (vpip->flag & EMLXS_VPI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_action:%d attempts=%d. Updating REG_VPI.", + vpip->VPI, + vpip->attempts); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_action:%d attempts=%d. Sending REG_VPI.", + vpip->VPI, + vpip->attempts); + } + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb = (MAILBOX*)mbq; + bzero((void *) mb, MAILBOX_CMD_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_vpi_reg_mbcmpl; + mbq->context = (void *)vpip; + mbq->port = (void *)vpip->port; + + mb->un.varRegVpi.vfi = vpip->vfip->VFI; + mb->un.varRegVpi.upd = (vpip->flag & EMLXS_VPI_REG)? 1:0; + + wwpn = (uint32_t *)&port->wwpn; + mb->un.varRegVpi.portname[0] = BE_SWAP32(*wwpn); + wwpn++; + mb->un.varRegVpi.portname[1] = BE_SWAP32(*wwpn); + + mb->un.varRegVpi.vpi = vpip->VPI; + mb->un.varRegVpi.sid = vpip->port->did; + mb->mbxCommand = MBX_REG_VPI; + mb->mbxOwner = OWN_HOST; + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_REG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + return (0); + +} /* emlxs_vpi_reg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_reg_cmpl_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_REG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "vpi_reg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_cmpl_action:%d attempts=%d. Offline requested.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_reg_cmpl_action:%d attempts=%d. Going online.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_state(port, vpip, VPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_vpi_reg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_vpi_online_action(emlxs_port_t *port, VPIobj_t *vpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (vpip->state != VPI_STATE_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + vpip->VPI, + emlxs_vpi_state_xlate(vpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + vpip->flag &= ~EMLXS_VPI_ONLINE_REQ; + + if (vpip->flag & EMLXS_VPI_OFFLINE_REQ) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_action:%d attempts=%d. Offline requested.", + vpip->VPI, + vpip->attempts); + + rval = emlxs_vpi_offline_handler(port, vpip, arg1); + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "vpi_online_action:%d. VPI online. Notifying VFI:%d", + vpip->VPI, + vpip->vfip->VFI); + + /* Notify VFI */ + rval = emlxs_vfi_event(port, FCF_EVENT_VPI_ONLINE, vpip); + + return (rval); + +} /* emlxs_vpi_online_action() */ + + +/* ************************************************************************** */ +/* RPI */ +/* ************************************************************************** */ + +static char * +emlxs_rpi_state_xlate(uint32_t state) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_rpi_state_table) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (state == emlxs_rpi_state_table[i].code) { + return (emlxs_rpi_state_table[i].string); + } + } + + (void) sprintf(buffer, "state=0x%x", state); + return (buffer); + +} /* emlxs_rpi_state_xlate() */ + + +static uint32_t +emlxs_rpi_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + uint32_t(*func) (emlxs_port_t *, RPIobj_t *, uint32_t, void *); + uint32_t index; + uint32_t events; + uint16_t state; + + /* Convert event to action table index */ + switch (evt) { + case FCF_EVENT_STATE_ENTER: + index = 0; + break; + case FCF_EVENT_RPI_ONLINE: + index = 1; + break; + case FCF_EVENT_RPI_OFFLINE: + index = 2; + break; + case FCF_EVENT_RPI_PAUSE: + index = 3; + break; + case FCF_EVENT_RPI_RESUME: + index = 4; + break; + default: + return (1); + } + + events = RPI_ACTION_EVENTS; + state = rpip->state; + + index += (state * events); + func = (uint32_t(*) (emlxs_port_t *, RPIobj_t *, uint32_t, void *)) + emlxs_rpi_action_table[index]; + + if (!func) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "rpi:%d %s:%s arg=%p. No action. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + rval = (func)(port, rpip, evt, arg1); + + return (rval); + +} /* emlxs_rpi_action() */ + + +static uint32_t +emlxs_rpi_event(emlxs_port_t *port, uint32_t evt, + void *arg1) +{ + RPIobj_t *rpip = NULL; + uint32_t rval; + + /* Filter events and acquire fcfi context */ + switch (evt) { + case FCF_EVENT_RPI_ONLINE: + case FCF_EVENT_RPI_OFFLINE: + case FCF_EVENT_RPI_PAUSE: + case FCF_EVENT_RPI_RESUME: + rpip = (RPIobj_t *)arg1; + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "rpi: %s arg=%p. Null RPI found. Terminated.", + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + break; + + default: + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_event_msg, + "rpi:%d %s:%s arg=%p", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + rval = emlxs_rpi_action(port, rpip, evt, arg1); + + return (rval); + +} /* emlxs_rpi_event() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_state(emlxs_port_t *port, RPIobj_t *rpip, uint16_t state, + uint16_t reason, uint32_t explain, void *arg1) +{ + uint32_t rval = 0; + + if (state >= RPI_ACTION_STATES) { + return (1); + } + + if ((rpip->state == state) && + (reason != FCF_REASON_REENTER)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_state:%d %s:%s:0x%x arg=%p. State not changed. " + "Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + + return (1); + } + + if (!reason) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "rpi:%d %s-->%s arg=%p", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_rpi_state_xlate(state), arg1); + } else if (reason == FCF_REASON_EVENT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "rpi:%d %s-->%s:%s:%s arg=%p", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_rpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + emlxs_fcf_event_xlate(explain), arg1); + } else if (explain) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "rpi:%d %s-->%s:%s:0x%x arg=%p", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_rpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), + explain, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_state_msg, + "rpi:%d %s-->%s:%s arg=%p", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_rpi_state_xlate(state), + emlxs_fcf_reason_xlate(reason), arg1); + } + + rpip->prev_state = rpip->state; + rpip->prev_reason = rpip->reason; + rpip->state = state; + rpip->reason = reason; + + rval = emlxs_rpi_action(port, rpip, FCF_EVENT_STATE_ENTER, arg1); + + return (rval); + +} /* emlxs_rpi_state() */ + + +static RPIobj_t * +emlxs_rpi_alloc(emlxs_port_t *port, uint32_t did) +{ + emlxs_hba_t *hba = HBA; + uint16_t i; + RPIobj_t *rpip; + + /* Special handling for Fabric RPI */ + if (did == FABRIC_DID) { + /* Use the reserved RPI in the port */ + rpip = &port->VPIobj.fcf_rpi; + + bzero(rpip, sizeof (RPIobj_t)); + rpip->index = 0xffff; + rpip->RPI = 0xffff; + rpip->did = FABRIC_DID; + rpip->vpip = &port->VPIobj; + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + 0, 0, 0); + + return (rpip); + } + + rpip = hba->sli.sli4.RPIp; + for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { + /* To be consistent with SLI3, the RPI assignment */ + /* starts with 1. ONLY one SLI4 HBA in the entire */ + /* system will be sacrificed by one RPI and that */ + /* is the one having RPI base equal 0. */ + if ((rpip->state == RPI_STATE_FREE) && (rpip->RPI != 0)) { + + bzero(rpip, sizeof (RPIobj_t)); + rpip->index = i; + rpip->RPI = hba->sli.sli4.RPIBase + i; + rpip->vpip = &port->VPIobj; + rpip->did = did; + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + 0, 0, 0); + + return (rpip); + } + } + + return (NULL); + +} /* emlxs_rpi_alloc() */ + + +static uint32_t +emlxs_rpi_free(emlxs_port_t *port, RPIobj_t *rpip) +{ + uint32_t rval; + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); + + return (rval); + +} /* emlxs_fcfi_free() */ + + +extern RPIobj_t * +emlxs_rpi_find(emlxs_port_t *port, uint16_t rpi) +{ + emlxs_hba_t *hba = HBA; + RPIobj_t *rpip; + + /* Special handling for Fabric RPI */ + if (rpi == 0xffff) { + return (port->VPIobj.rpip); + } + + if ((rpi < hba->sli.sli4.RPIBase) || + (rpi >= hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_find:%d. RPI out of range (%d,%d).", + rpi, + hba->sli.sli4.RPIBase, + hba->sli.sli4.RPIBase+hba->sli.sli4.RPICount); + + return (NULL); + } + + rpip = &hba->sli.sli4.RPIp[(rpi - hba->sli.sli4.RPIBase)]; + + if (rpip->state == RPI_STATE_FREE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_find:%d RPI not active", + rpi); + + return (NULL); + } + + return (rpip); + +} /* emlxs_rpi_find() */ + + +static RPIobj_t * +emlxs_rpi_find_did(emlxs_port_t *port, uint32_t did) +{ + emlxs_hba_t *hba = HBA; + RPIobj_t *rpip; + RPIobj_t *rpip1; + uint32_t i; + + /* Special handling for Fabric RPI */ + if (did == FABRIC_DID) { + return (port->VPIobj.rpip); + } + + rpip1 = NULL; + rpip = hba->sli.sli4.RPIp; + for (i = 0; i < hba->sli.sli4.RPICount; i++, rpip++) { + if (rpip->state == RPI_STATE_FREE) { + continue; + } + + if ((rpip->did == did) && (rpip->vpip == &port->VPIobj)) { + rpip1 = rpip; + break; + } + } + + return (rpip1); + +} /* emlxs_rpi_find_did() */ + + +extern RPIobj_t * +emlxs_rpi_alloc_notify(emlxs_port_t *port, uint32_t did) +{ + emlxs_hba_t *hba = HBA; + RPIobj_t *rpip; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (NULL); + } + + /* Fabric RPI will be handled automatically */ + if (did == FABRIC_DID) { + return (NULL); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rpip = emlxs_rpi_alloc(port, did); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rpip); + +} /* emlxs_rpi_alloc_notify() */ + + +extern uint32_t +emlxs_rpi_free_notify(emlxs_port_t *port, RPIobj_t *rpip) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!rpip) { + return (1); + } + + /* Fabric RPI will be handled automatically */ + if (rpip->did == FABRIC_DID) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + rval = emlxs_rpi_free(port, rpip); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (rval); + +} /* emlxs_rpi_free_notify() */ + + +extern uint32_t +emlxs_rpi_pause_notify(emlxs_port_t *port, RPIobj_t *rpip) +{ + emlxs_hba_t *hba = HBA; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_pause_notify: No RPI provided."); + + return (1); + } + + /* Fabric RPI will be handled automatically */ + if (rpip->did == FABRIC_DID) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_pause_notify:%d %s. Pausing.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_PAUSE, rpip); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (0); + +} /* emlxs_rpi_pause_notify() */ + + +extern uint32_t +emlxs_rpi_online_notify(emlxs_port_t *port, RPIobj_t *rpip, uint32_t did, + SERV_PARM *sparam, void *arg1, void *arg2, void *arg3) +{ + emlxs_hba_t *hba = HBA; + emlxs_deferred_cmpl_t *cmpl; + uint32_t allocated = 0; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (1); + } + + /* Fabric RPI will be handled automatically */ + if (did == FABRIC_DID) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_notify: vpi=%d. Port disabled.", + port->VPIobj.VPI); + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + if (!rpip) { + rpip = emlxs_rpi_find_did(port, did); + } + + if (!rpip) { + rpip = emlxs_rpi_alloc(port, did); + allocated = 1; + } + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_notify: Unable to allocate an rpi. did=%x", + did); + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + /* Initialize RPI node info */ + bcopy((void *)sparam, (void *)&rpip->sparam, sizeof (SERV_PARM)); + + if (arg1 || arg2 || arg3) { + cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( + sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); + + cmpl->port = port; + cmpl->arg1 = arg1; + cmpl->arg2 = arg2; + cmpl->arg3 = arg3; + + rpip->cmpl = cmpl; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_notify:%d %s. %s. Onlining.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + ((allocated)? "Allocated":"Updated")); + + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_ONLINE, rpip); + + if (rpip->cmpl) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_online_notify:%d %s. Deferred args not completed.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (0); + +} /* emlxs_rpi_online_notify() */ + + +extern uint32_t +emlxs_rpi_offline_notify(emlxs_port_t *port, RPIobj_t *rpip, + void *arg1, void *arg2, void *arg3) +{ + emlxs_hba_t *hba = HBA; + emlxs_deferred_cmpl_t *cmpl; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_offline_notify: No RPI provided."); + + return (1); + } + + /* Fabric RPI will be handled automatically */ + if (rpip->did == FABRIC_DID) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (arg1 || arg2 || arg3) { + cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( + sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); + + cmpl->port = port; + cmpl->arg1 = arg1; + cmpl->arg2 = arg2; + cmpl->arg3 = arg3; + + rpip->cmpl = cmpl; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_notify:%d %s. Offlining.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip); + + if (rpip->cmpl) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_offline_notify:%d %s. Deferred args not completed.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (0); + +} /* emlxs_rpi_offline_notify() */ + + +extern uint32_t +emlxs_rpi_resume_notify(emlxs_port_t *port, RPIobj_t *rpip, emlxs_buf_t *sbp) +{ + emlxs_hba_t *hba = HBA; + emlxs_deferred_cmpl_t *cmpl; + + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + return (1); + } + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_notify: No RPI provided."); + + return (1); + } + + /* Fabric RPI will be handled automatically */ + if (rpip->did == FABRIC_DID) { + return (1); + } + + mutex_enter(&EMLXS_FCF_LOCK); + + if (rpip->state != RPI_STATE_PAUSED) { + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + if (sbp) { + cmpl = (emlxs_deferred_cmpl_t *)kmem_zalloc( + sizeof (emlxs_deferred_cmpl_t), KM_SLEEP); + + cmpl->port = port; + cmpl->arg1 = (void *)sbp; + cmpl->arg2 = 0; + cmpl->arg3 = 0; + + rpip->cmpl = cmpl; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_notify:%d %s. Resuming.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + (void) emlxs_rpi_event(port, FCF_EVENT_RPI_RESUME, rpip); + + if (rpip->cmpl) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_notify:%d %s. Deferred args not completed.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + + mutex_exit(&EMLXS_FCF_LOCK); + return (1); + } + + mutex_exit(&EMLXS_FCF_LOCK); + + return (0); + +} /* emlxs_rpi_resume_notify() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_free_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + XRIobj_t *xrip; + XRIobj_t *next_xrip; + + if (rpip->state != RPI_STATE_FREE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_free_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (rpip->did == FABRIC_DID) { + if (rpip->vpip->flogi_sbp) { + emlxs_vpi_flogi_cmpl(port, rpip->vpip, 1); + } + } + + /* Break node/RPI binding */ + rw_enter(&port->node_rwlock, RW_WRITER); + if (rpip->node) { + rpip->node->rpip = NULL; + rpip->node = NULL; + } + rw_exit(&port->node_rwlock); + + /* Remove all XRIs under this RPI */ + mutex_enter(&EMLXS_FCTAB_LOCK); + xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; + while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { + next_xrip = xrip->_f; + if (xrip->rpip == rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_free_action:%d xri_count=%d. " + "Removing XRI:%d iotag:%d.", + rpip->RPI, + rpip->xri_count, + xrip->XRI, xrip->iotag); + + xrip->rpip->xri_count--; + xrip->rpip = NULL; + } + xrip = next_xrip; + } + mutex_exit(&EMLXS_FCTAB_LOCK); + + if (rpip->xri_count) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_free_action:%d. xri_count=%d", + rpip->RPI, + rpip->xri_count); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_free_action:%d flag=%x. RPI freed.", + rpip->RPI, + rpip->flag); + + rpip->flag = 0; + + return (0); + +} /* emlxs_rpi_free_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_online_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 1; + + if (evt != FCF_EVENT_RPI_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_online_evt_action:%d %s:%s arg=%p. " + "Invalid event type. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + switch (rpip->state) { + case RPI_STATE_REG: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_evt_action:%d flag=%x. Registering.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG, + FCF_REASON_REENTER, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_evt_action:%d flag=%x. Registering.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG, + FCF_REASON_EVENT, evt, arg1); + break; + } + + return (rval); + +} /* emlxs_rpi_online_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_offline_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 1; + + if (evt != FCF_EVENT_RPI_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_offline_evt_action:%d %s:%s arg=%p. " + "Invalid event type. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + switch (rpip->state) { + case RPI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_evt_action:%d flag=%x. Offlining RPI.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case RPI_STATE_UNREG: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_evt_action:%d flag=%x. Already unregistering. " + "Terminated.", + rpip->RPI, + rpip->flag); + + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_evt_action:%d flag=%x. Unregistering.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, + FCF_REASON_EVENT, evt, arg1); + break; + + } + + return (rval); + +} /* emlxs_rpi_offline_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_pause_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 1; + + if (evt != FCF_EVENT_RPI_PAUSE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_pause_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1, + rpip->flag); + return (1); + } + + switch (rpip->state) { + case RPI_STATE_OFFLINE: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_pause_evt_action:%d flag=%x. Offlining RPI.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_REENTER, evt, arg1); + break; + + case RPI_STATE_UNREG: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_pause_evt_action:%d flag=%x. Not online. " + "Terminated.", + rpip->RPI, + rpip->flag); + + break; + + case RPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_pause_evt_action:%d flag=%x. Already paused. " + "Terminated.", + rpip->RPI, + rpip->flag); + + break; + + case RPI_STATE_REG: + case RPI_STATE_ONLINE: + case RPI_STATE_RESUME: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_pause_evt_action:%d flag=%x. Pausing.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_PAUSED, + FCF_REASON_EVENT, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_pause_evt_action:%d flag=%x. Terminated.", + rpip->RPI, + rpip->flag); + break; + } + + return (rval); + +} /* emlxs_rpi_pause_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_resume_evt_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval = 1; + + if (evt != FCF_EVENT_RPI_RESUME) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_evt_action:%d %s:%s arg=%p flag=%x. " + "Invalid event type. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1, + rpip->flag); + return (1); + } + + switch (rpip->state) { + case RPI_STATE_PAUSED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_evt_action:%d flag=%x. Resuming.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME, + FCF_REASON_EVENT, evt, arg1); + break; + + default: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_evt_action:%d flag=%x. Not paused. Terminated.", + rpip->RPI, + rpip->flag); + break; + } + + return (rval); + +} /* emlxs_rpi_resume_evt_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_offline_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + VPIobj_t *vpip; + + vpip = rpip->vpip; + + if (rpip->state != RPI_STATE_OFFLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (rpip->prev_state == RPI_STATE_FREE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_action:%d rpi_online=%d,%d. Terminated.", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused); + + return (0); + } + + if (rpip->flag & EMLXS_RPI_PAUSED) { + rpip->flag &= ~EMLXS_RPI_PAUSED; + + if (vpip->rpi_paused) { + vpip->rpi_paused--; + } + } + + if (rpip->flag & EMLXS_RPI_VPI) { + rpip->flag &= ~EMLXS_RPI_VPI; + + if (vpip->rpi_online) { + vpip->rpi_online--; + } + + /* Added protection */ + if (vpip->rpi_online < vpip->rpi_paused) { + vpip->rpi_paused = vpip->rpi_online; + } + } + + if (rpip->did == FABRIC_DID) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " + "Fabric RPI offline. Freeing.", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->xri_count); + + /* Free RPI */ + rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); + + return (rval); + } + + if ((vpip->rpi_online == 0) || + (vpip->rpi_online == vpip->rpi_paused)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " + "RPI offline. " + "Notifying VPI:%d", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->xri_count, + vpip->VPI); + + /* Notify VPI */ + (void) emlxs_vpi_event(port, FCF_EVENT_RPI_OFFLINE, rpip); + + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_offline_action:%d rpi_online=%d,%d xri_count=%d. " + "RPI offline. Freeing.", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->xri_count); + } + + /* Free RPI */ + rval = emlxs_rpi_state(port, rpip, RPI_STATE_FREE, 0, 0, 0); + + return (rval); + +} /* emlxs_rpi_offline_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_paused_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + VPIobj_t *vpip; + + vpip = rpip->vpip; + + if (rpip->state != RPI_STATE_PAUSED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_paused_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (!(rpip->flag & EMLXS_RPI_PAUSED)) { + rpip->flag |= EMLXS_RPI_PAUSED; + vpip->rpi_paused++; + } + + /* Check if all RPI's have been paused for a VPI */ + if (vpip->rpi_online == vpip->rpi_paused) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. " + "RPI paused. " + "Notifying VPI:%d", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->xri_count, + vpip->VPI); + + /* Notify VPI */ + (void) emlxs_vpi_event(port, FCF_EVENT_RPI_PAUSE, rpip); + + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_paused_action:%d rpi_online=%d,%d xri_count=%d. " + "RPI paused.", + rpip->RPI, + vpip->rpi_online, vpip->rpi_paused, + rpip->xri_count); + } + + return (0); + +} /* emlxs_rpi_paused_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_unreg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + rpip->attempts++; + + if (rpip->state != RPI_STATE_UNREG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_unreg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1, + rpip->attempts); + + return (1); + } + + if ((rpip->reason == FCF_REASON_SEND_FAILED) || + !(rpip->flag & EMLXS_RPI_REG)) { + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_failed_action:%d reason=%x flag=%x. " + "Going offline.", + rpip->RPI, + rpip->reason, + rpip->flag); + + rpip->flag &= ~EMLXS_RPI_REG; + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_failed_action:%d flag=%x. Going online.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_rpi_unreg_failed_action() */ + + +static void +emlxs_rpi_unreg_handler(emlxs_port_t *port, RPIobj_t *rpip) +{ + emlxs_hba_t *hba = HBA; + VPIobj_t *vpip = rpip->vpip; + emlxs_node_t *node = rpip->node; + XRIobj_t *xrip; + XRIobj_t *next_xrip; + + /* Special handling for Fabric RPI */ + if (rpip->did == FABRIC_DID) { + if (node) { + (void) emlxs_tx_node_flush(port, node, 0, 0, 0); + (void) emlxs_chipq_node_flush(port, 0, node, 0); + } + + /* Clear all reserved XRIs under this RPI */ + mutex_enter(&EMLXS_FCTAB_LOCK); + xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; + while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { + next_xrip = xrip->_f; + if ((xrip->rpip == rpip) && + (xrip->flag & EMLXS_XRI_RESERVED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_action:%d xri_count=%d. " + "Unreserving XRI:%d iotag:%d.", + rpip->RPI, + rpip->xri_count, + xrip->XRI, xrip->iotag); + + (void) emlxs_sli4_unreserve_xri(hba, + xrip->XRI, 0); + } + xrip = next_xrip; + } + mutex_exit(&EMLXS_FCTAB_LOCK); + } + + rpip->flag &= ~EMLXS_RPI_REG; + + if (rpip->flag & EMLXS_RPI_PAUSED) { + rpip->flag &= ~EMLXS_RPI_PAUSED; + + if (vpip->rpi_paused) { + vpip->rpi_paused--; + } + } + + if (rpip->flag & EMLXS_RPI_VPI) { + rpip->flag &= ~EMLXS_RPI_VPI; + + if (vpip->rpi_online) { + vpip->rpi_online--; + } + + /* Added protection */ + if (vpip->rpi_online < vpip->rpi_paused) { + vpip->rpi_paused = vpip->rpi_online; + } + } + + rw_enter(&port->node_rwlock, RW_WRITER); + if (node) { + rpip->node = NULL; + node->rpip = NULL; + } + rw_exit(&port->node_rwlock); + + if (node) { + emlxs_node_rm(port, node); + } + + return; + +} /* emlxs_rpi_unreg_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_unreg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + RPIobj_t *rpip; + + mutex_enter(&EMLXS_FCF_LOCK); + + rpip = (RPIobj_t *)mbq->context; + + mb4 = (MAILBOX4 *)mbq; + + if (rpip->state != RPI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_mbcmpl:%d state=%s. " + "No longer in RPI_STATE_UNREG. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_mbcmpl:%d failed. status=%x", + rpip->RPI, + mb4->mbxStatus); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + emlxs_rpi_unreg_handler(port, rpip); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_mbcmpl:%d Unregistered. Unreg cmpl.", + rpip->RPI); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_CMPL, + 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + +} /* emlxs_rpi_unreg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_unreg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + VPIobj_t *vpip = rpip->vpip; + + if (rpip->state != RPI_STATE_UNREG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_unreg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (!(rpip->flag & EMLXS_RPI_REG)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_action:%d. Not registered. Going offline.", + rpip->RPI); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (rpip->prev_state != RPI_STATE_UNREG_FAILED) { + rpip->attempts = 0; + } + + if (rpip->did == FABRIC_DID) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_action:%d did=%x vpi=%d. Fabric RPI. " + "Going offline.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + /* Don't send UNREG_RPI, but process it as if we did */ + emlxs_rpi_unreg_handler(port, rpip); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_action:%d attempts=%d. Sending UNREG_RPI.", + rpip->RPI, + rpip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_rpi_unreg_mbcmpl; + mbq->context = (void *)rpip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_UNREG_RPI; + mb4->mbxOwner = OWN_HOST; + mb4->un.varUnregLogin.rpi = rpip->RPI; + mb4->un.varUnregLogin.vpi = vpip->VPI; + + if (rpip->cmpl) { + mbq->sbp = rpip->cmpl->arg1; + mbq->ubp = rpip->cmpl->arg2; + mbq->iocbq = rpip->cmpl->arg3; + } + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + if (rpip->cmpl) { + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + } + + return (0); + +} /* emlxs_rpi_unreg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_unreg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (rpip->state != RPI_STATE_UNREG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_unreg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_unreg_cmpl_action:%d flag=%x. Going offline.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + +} /* emlxs_rpi_unreg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_reg_failed_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + rpip->attempts++; + + if (rpip->state != RPI_STATE_REG_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_reg_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1, + rpip->attempts); + + return (1); + } + + if ((rpip->reason == FCF_REASON_SEND_FAILED) || + !(rpip->flag & EMLXS_RPI_REG)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_failed_action:%d reason=%x flag=%x. " + "Going offline.", + rpip->RPI, + rpip->reason, + rpip->flag); + + rpip->flag &= ~EMLXS_RPI_REG; + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_failed_action:%d flag=%x. Unregistering", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_rpi_reg_failed_action() */ + + +static uint32_t +emlxs_rpi_reg_handler(emlxs_port_t *port, RPIobj_t *rpip) +{ + VPIobj_t *vpip; + emlxs_node_t *node; + + vpip = rpip->vpip; + + rpip->flag |= EMLXS_RPI_REG; + + if (rpip->flag & EMLXS_RPI_PAUSED) { + rpip->flag &= ~EMLXS_RPI_PAUSED; + + if (vpip->rpi_paused) { + vpip->rpi_paused--; + } + } + + if (!(rpip->flag & EMLXS_RPI_VPI) && + (rpip->did != FABRIC_DID)) { + rpip->flag |= EMLXS_RPI_VPI; + vpip->rpi_online++; + } + + /* Create or update the node */ + node = emlxs_node_create(port, rpip->did, rpip->RPI, &rpip->sparam); + + if (!node) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_handler:%d. Node create failed. Reg failed.", + rpip->RPI); + + return (FCF_REASON_NO_NODE); + } + + return (0); + +} /* emlxs_rpi_reg_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_reg_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + RPIobj_t *rpip; + emlxs_node_t *node; + uint32_t rval; + + mutex_enter(&EMLXS_FCF_LOCK); + + rpip = (RPIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + if (rpip->state != RPI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_mbcmpl:%d state=%s. No longer in RPI_STATE_REG. " + "Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_mbcmpl:%d failed. status=%x", + rpip->RPI, + mb4->mbxStatus); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + rval = emlxs_rpi_reg_handler(port, rpip); + + if (rval) { + mb4->mbxStatus = MBX_FAILURE; + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + rval, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + node = rpip->node; + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_mbcmpl:%d Registered. Reg cmpl.", + rpip->RPI); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_REG_CMPL, 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + + /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */ + if (mbq->sbp) { + ((emlxs_buf_t *)mbq->sbp)->node = node; + } + +#ifdef DHCHAP_SUPPORT + if (mbq->sbp || mbq->ubp) { + if (emlxs_dhc_auth_start(port, node, (uint8_t *)mbq->sbp, + (uint8_t *)mbq->ubp) == 0) { + /* Auth started - auth completion will */ + /* handle sbp and ubp now */ + mbq->sbp = NULL; + mbq->ubp = NULL; + } + } +#endif /* DHCHAP_SUPPORT */ + + return (0); + +} /* emlxs_rpi_reg_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_reg_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + MATCHMAP *mp; + uint32_t rval; + + if (rpip->state != RPI_STATE_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_reg_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (rpip->did == FABRIC_DID) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_action:%d did=%x vpi=%d. Fabric RPI. " + "Going online.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + /* Don't send REG_RPI, but process it as if we did */ + rval = emlxs_rpi_reg_handler(port, rpip); + + if (rval) { + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + rval, 0, 0); + + return (rval); + } + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_action:%d did=%x. vpi=%d. Port disabled. " + "Offlining RPI.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_NOT_ALLOWED, evt, arg1); + + return (rval); + } + + if (rpip->prev_state != RPI_STATE_REG_FAILED) { + rpip->attempts = 0; + } + + if (rpip->flag & EMLXS_RPI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_action:%d flag=%x. Already registered. " + "Updating registration.", + rpip->RPI, rpip->flag); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_action:%d attempts=%d. Sending REG_RPI.", + rpip->RPI, + rpip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + FCF_REASON_NO_BUFFER, 0, arg1); + + return (rval); + } + + mbq->bp = (void *)mp; + mbq->nonembed = NULL; + + mbq->mbox_cmpl = emlxs_rpi_reg_mbcmpl; + mbq->context = (void *)rpip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_REG_RPI; + mb4->mbxOwner = OWN_HOST; + + mb4->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); + mb4->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys); + mb4->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys); + mb4->un.varRegLogin.did = rpip->did; + mb4->un.varWords[30] = 0; /* flags */ + + mb4->un.varRegLogin.vpi = rpip->vpip->VPI; + mb4->un.varRegLogin.rpi = rpip->RPI; + + bcopy((void *)&rpip->sparam, (void *)mp->virt, sizeof (SERV_PARM)); + + if (rpip->cmpl) { + mbq->sbp = rpip->cmpl->arg1; + mbq->ubp = rpip->cmpl->arg2; + mbq->iocbq = rpip->cmpl->arg3; + } + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_REG_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + if (rpip->cmpl) { + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + } + + return (0); + +} /* emlxs_rpi_reg_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_reg_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (rpip->state != RPI_STATE_REG_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_reg_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (rpip->flag & EMLXS_RPI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_cmpl_action:%d flag=%x. Going online", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_cmpl_action:%d flag=%x. Going offline.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_rpi_reg_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_resume_failed_action(emlxs_port_t *port, RPIobj_t *rpip, + uint32_t evt, void *arg1) +{ + uint32_t rval; + + rpip->attempts++; + + if (rpip->state != RPI_STATE_RESUME_FAILED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_failed_action:%d %s:%s arg=%p attempt=%d. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1, + rpip->attempts); + + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_failed_action:%d attempt=%d. Unregistering.", + rpip->RPI, + rpip->attempts); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + + return (rval); + +} /* emlxs_rpi_resume_failed_action() */ + + +/*ARGSUSED*/ +static void +emlxs_rpi_resume_handler(emlxs_port_t *port, RPIobj_t *rpip) +{ + if (rpip->flag & EMLXS_RPI_PAUSED) { + rpip->flag &= ~EMLXS_RPI_PAUSED; + + if (rpip->vpip->rpi_paused) { + rpip->vpip->rpi_paused--; + } + } + + return; + +} /* emlxs_rpi_resume_handler() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_resume_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) +{ + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX4 *mb4; + RPIobj_t *rpip; + + mutex_enter(&EMLXS_FCF_LOCK); + + rpip = (RPIobj_t *)mbq->context; + mb4 = (MAILBOX4 *)mbq; + + if (rpip->state != RPI_STATE_RESUME) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_mbcmpl:%d state=%s. " + "No longer in RPI_STATE_RESUME. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state)); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + if (mb4->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_mbcmpl:%d failed. status=%x", + rpip->RPI, + mb4->mbxStatus); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, + FCF_REASON_MBOX_FAILED, mb4->mbxStatus, (void *)mbq->sbp); + + mutex_exit(&EMLXS_FCF_LOCK); + return (0); + } + + emlxs_rpi_resume_handler(port, rpip); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_mbcmpl:%d Resumed. Resume cmpl.", + rpip->RPI); + + (void) emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_CMPL, 0, 0, 0); + + mutex_exit(&EMLXS_FCF_LOCK); + + return (0); + +} /* emlxs_rpi_resume_mbcmpl() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_resume_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + MAILBOX4 *mb4; + MAILBOXQ *mbq; + uint32_t rval; + + if (rpip->state != RPI_STATE_RESUME) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + + return (1); + } + + if (!(rpip->flag & EMLXS_RPI_PAUSED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_action:%d flag=%x. Not Paused. Going online.", + rpip->RPI, rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (rpip->did == FABRIC_DID) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_action:%d. Fabric RPI. " + "Going online.", + rpip->RPI); + + /* Don't send RESUME_RPI, but process it as if we did */ + emlxs_rpi_resume_handler(port, rpip); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_EVENT, evt, arg1); + + return (rval); + } + + if (rpip->prev_state != RPI_STATE_RESUME_FAILED) { + rpip->attempts = 0; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_action:%d attempts=%d. Sending RESUME_RPI.", + rpip->RPI, + rpip->attempts); + + if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, + FCF_REASON_NO_MBOX, 0, arg1); + + return (rval); + } + mb4 = (MAILBOX4*)mbq; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + + mbq->nonembed = NULL; + mbq->mbox_cmpl = emlxs_rpi_resume_mbcmpl; + mbq->context = (void *)rpip; + mbq->port = (void *)port; + + mb4->mbxCommand = MBX_RESUME_RPI; + mb4->mbxOwner = OWN_HOST; + + mb4->un.varResumeRPI.EventTag = hba->link_event_tag; + mb4->un.varResumeRPI.RPI = rpip->RPI; + + if (rpip->cmpl) { + mbq->sbp = rpip->cmpl->arg1; + mbq->ubp = rpip->cmpl->arg2; + mbq->iocbq = rpip->cmpl->arg3; + } + + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_RESUME_FAILED, + FCF_REASON_SEND_FAILED, rval, arg1); + + return (rval); + } + + if (rpip->cmpl) { + kmem_free(rpip->cmpl, sizeof (emlxs_deferred_cmpl_t)); + rpip->cmpl = 0; + } + + return (0); + +} /* emlxs_rpi_resume_action() */ + + +static uint32_t +emlxs_rpi_resume_cmpl_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + uint32_t rval; + + if (rpip->state != RPI_STATE_RESUME_CMPL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_error_msg, + "rpi_resume_cmpl_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (rpip->flag & EMLXS_RPI_PAUSED) { + if (rpip->flag & EMLXS_RPI_REG) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_cmpl_action:%d flag=%x. Unregistering.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_UNREG, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_reg_cmpl_action:%d flag=%x. Going offline.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_resume_cmpl_action:%d flag=%x. Going online.", + rpip->RPI, + rpip->flag); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_ONLINE, + FCF_REASON_OP_FAILED, rpip->attempts, arg1); + } + + return (rval); + +} /* emlxs_rpi_resume_cmpl_action() */ + + +/*ARGSUSED*/ +static uint32_t +emlxs_rpi_online_action(emlxs_port_t *port, RPIobj_t *rpip, uint32_t evt, + void *arg1) +{ + emlxs_hba_t *hba = HBA; + uint32_t rval; + + if (rpip->state != RPI_STATE_ONLINE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_action:%d %s:%s arg=%p. " + "Invalid state. Terminated.", + rpip->RPI, + emlxs_rpi_state_xlate(rpip->state), + emlxs_fcf_event_xlate(evt), arg1); + return (1); + } + + if (rpip->did == FABRIC_DID) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_action:%d did=%x. Fabric RPI online. " + "Terminated.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + EMLXS_STATE_CHANGE(hba, FC_READY); + + if (rpip->vpip->flogi_sbp) { + emlxs_vpi_flogi_cmpl(port, rpip->vpip, 0); + } + + return (0); + } + + if (!(rpip->vpip->flag & EMLXS_VPI_PORT_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_action:%d did=%x. vpi=%d. Port disabled. " + "Offlining RPI.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + rval = emlxs_rpi_state(port, rpip, RPI_STATE_OFFLINE, + FCF_REASON_NOT_ALLOWED, evt, arg1); + + return (rval); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcf_detail_msg, + "rpi_online_action:%d did=%x. RPI online. Notifying VPI:%d.", + rpip->RPI, + rpip->did, + rpip->vpip->VPI); + + /* Notify VPI */ + rval = emlxs_vpi_event(port, FCF_EVENT_RPI_ONLINE, rpip); + + return (rval); + +} /* emlxs_rpi_online_action() */ diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c index b05483103a..a6fcb21b4d 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2010 Emulex. All rights reserved. + * Copyright 2011 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -211,6 +211,7 @@ emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) * transferred. We saw a data corruption when Solaris received * a Task Abort from a tape. */ + if (scsi_status == SCSI_STAT_TASK_ABORT) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, @@ -487,9 +488,10 @@ if (cfg[CFG_ENABLE_PATCH].current & FCP_UNDERRUN_PATCH2) { default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fcp_completion_error_msg, - "Local reject. %s did=0x%06x sbp=%p cmd=%02x", + "Local reject. %s 0x%06x %p %02x (%x)(%x)", emlxs_error_xlate(localstat), did, sbp, - scsi_opcode); + scsi_opcode, (uint16_t)cmd->ULPIOTAG, + (uint16_t)cmd->ULPCONTEXT); } break; @@ -659,15 +661,14 @@ emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) for (j = 0; j < i; j++) { mp = EMLXS_GET_VADDR(hba, rp, icmd); if (mp) { - (void) emlxs_mem_put(hba, seg, - (uint8_t *)mp); + emlxs_mem_put(hba, seg, + (void *)mp); } } rp->fc_missbufcnt = cnt + i; - (void) emlxs_mem_put(hba, MEM_IOCB, - (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); return (cnt + i); } @@ -700,7 +701,7 @@ emlxs_post_buffer(emlxs_hba_t *hba, RING *rp, int16_t cnt) icmd->ULPLE = 1; icmd->ULPOWNER = OWN_CHIP; /* used for delimiter between commands */ - iocbq->bp = (uint8_t *)mp; + iocbq->bp = (void *)mp; EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[rp->ringno], iocbq); } @@ -728,6 +729,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) uint32_t unreg_vpi; uint32_t update; uint32_t adisc_support; + uint32_t clear_all; uint8_t format; /* Target mode only uses this routine for linkdowns */ @@ -741,6 +743,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) vlinkdown = 0; unreg_vpi = 0; update = 0; + clear_all = 0; if (!(port->flag & EMLXS_PORT_BOUND)) { return (0); @@ -765,6 +768,12 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) mask = 0x00000000; break; + case 0xfd: /* New fabric */ + mask = 0x00000000; + linkdown = 1; + clear_all = 1; + break; + #ifdef DHCHAP_SUPPORT case 0xfe: /* Virtual link down */ mask = 0x00000000; @@ -791,11 +800,13 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) mutex_enter(&EMLXS_PORT_LOCK); port->flag &= EMLXS_PORT_LINKDOWN_MASK; - port->prev_did = port->did; - port->did = 0; if (port->ulp_statec != FC_STATE_OFFLINE) { port->ulp_statec = FC_STATE_OFFLINE; + port->prev_did = port->did; + bcopy(&port->fabric_sparam, &port->prev_fabric_sparam, + sizeof (SERV_PARM)); + port->did = 0; update = 1; } @@ -909,7 +920,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) } rw_exit(&port->node_rwlock); - if (hba->flag & FC_ONLINE_MODE) { + if (!clear_all && (hba->flag & FC_ONLINE_MODE)) { adisc_support = cfg[CFG_ADISC_SUPPORT].current; } else { adisc_support = 0; @@ -922,7 +933,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) for (;;) { /* * We need to hold the locks this way because - * emlxs_mb_unreg_did and the flush routines enter the + * emlxs_mb_unreg_node and the flush routines enter the * same locks. Also, when we release the lock the list * can change out from under us. */ @@ -967,7 +978,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) if (action == 0) { break; } else if (action == 1) { - (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, + (void) emlxs_mb_unreg_node(port, nlp, NULL, NULL, NULL); } else if (action == 2) { #ifdef DHCHAP_SUPPORT @@ -1000,7 +1011,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) /* * We need to hold the locks this way because - * emlxs_mb_unreg_did and the flush routines enter the + * emlxs_mb_unreg_node and the flush routines enter the * same locks. Also, when we release the lock the list * can change out from under us. */ @@ -1058,7 +1069,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) if (action == 0) { break; } else if (action == 1) { - (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, + (void) emlxs_mb_unreg_node(port, nlp, NULL, NULL, NULL); } else if (action == 2) { #ifdef DHCHAP_SUPPORT @@ -1083,6 +1094,11 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) } else if (action == 3) { /* FCP2 devices */ unreg_vpi = 0; + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_rpi_pause_notify(port, + nlp->rpip); + } + #ifdef DHCHAP_SUPPORT emlxs_dhc_auth_stop(port, nlp); #endif /* DHCHAP_SUPPORT */ @@ -1124,7 +1140,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) for (;;) { /* * We need to hold the locks this way because - * emlxs_mb_unreg_did and the flush routines enter the + * emlxs_mb_unreg_node and the flush routines enter the * same locks. Also, when we release the lock the list * can change out from under us. */ @@ -1179,7 +1195,7 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) if (action == 0) { break; } else if (action == 1) { - (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, + (void) emlxs_mb_unreg_node(port, nlp, NULL, NULL, NULL); } else if (action == 2) { /* @@ -1200,6 +1216,11 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) } else if (action == 3) { /* FCP2 devices */ unreg_vpi = 0; + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_rpi_pause_notify(port, + nlp->rpip); + } + /* * Close the node for any further normal IO * An ADISC or a PLOGI with reopen the node @@ -1233,10 +1254,8 @@ emlxs_port_offline(emlxs_port_t *port, uint32_t scope) done: - if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { - if (unreg_vpi) { - (void) emlxs_mb_unreg_vpi(port); - } + if (unreg_vpi) { + (void) emlxs_mb_unreg_vpi(port); } return (0); @@ -1400,12 +1419,13 @@ emlxs_port_online(emlxs_port_t *vport) } /* emlxs_port_online() */ +/* SLI3 */ extern void emlxs_linkdown(emlxs_hba_t *hba) { emlxs_port_t *port = &PPORT; - RPIobj_t *rp; int i; + uint32_t scope; mutex_enter(&EMLXS_PORT_LOCK); @@ -1414,21 +1434,14 @@ emlxs_linkdown(emlxs_hba_t *hba) EMLXS_STATE_CHANGE_LOCKED(hba, FC_LINK_DOWN); } + /* Set scope */ + scope = (hba->flag & FC_NEW_FABRIC)? 0xFDFFFFFF:0xFFFFFFFF; + /* Filter hba flags */ hba->flag &= FC_LINKDOWN_MASK; hba->discovery_timer = 0; hba->linkup_timer = 0; - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - rp = hba->sli.sli4.RPIp; - for (i = 0; i < hba->sli.sli4.RPICount; i++) { - if (rp->state & RESOURCE_ALLOCATED) { - rp->state |= RESOURCE_RPI_PAUSED; - } - rp++; - } - } - mutex_exit(&EMLXS_PORT_LOCK); for (i = 0; i < MAX_VPORTS; i++) { @@ -1438,15 +1451,18 @@ emlxs_linkdown(emlxs_hba_t *hba) continue; } - (void) emlxs_port_offline(port, 0xffffffff); + (void) emlxs_port_offline(port, scope); } + emlxs_log_link_event(port); + return; } /* emlxs_linkdown() */ +/* SLI3 */ extern void emlxs_linkup(emlxs_hba_t *hba) { @@ -1470,6 +1486,8 @@ emlxs_linkup(emlxs_hba_t *hba) cv_broadcast(&EMLXS_LINKUP_CV); mutex_exit(&EMLXS_LINKUP_LOCK); + emlxs_log_link_event(port); + return; } #endif /* MENLO_SUPPORT */ @@ -1482,6 +1500,8 @@ emlxs_linkup(emlxs_hba_t *hba) mutex_exit(&EMLXS_PORT_LOCK); + emlxs_log_link_event(port); + return; } /* emlxs_linkup() */ @@ -1517,6 +1537,14 @@ emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) goto reset_link_fail; } + if (linkup) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, + "Resetting link..."); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, + "Disabling link..."); + } + mb = (MAILBOX *)mbq; /* Bring link down first */ @@ -1536,9 +1564,6 @@ emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) goto reset_link_fail; } - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_reset_msg, - "Disabling link..."); - if (linkup) { /* * Setup and issue mailbox INITIALIZE LINK command @@ -1583,7 +1608,7 @@ emlxs_reset_link(emlxs_hba_t *hba, uint32_t linkup, uint32_t wait) reset_link_fail: if ((wait == MBX_WAIT) && mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } return (rval); @@ -1709,8 +1734,11 @@ emlxs_offline(emlxs_hba_t *hba) "Going offline..."); if (port->ini_mode) { - /* Flush all IO */ - emlxs_linkdown(hba); + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_fcf_shutdown_notify(port, 1); + } else { + emlxs_linkdown(hba); + } } #ifdef SFCT_SUPPORT else { @@ -1783,26 +1811,12 @@ emlxs_power_down(emlxs_hba_t *hba) emlxs_port_t *port = &PPORT; #endif /* FMA_SUPPORT */ int32_t rval = 0; - uint32_t *ptr; - uint32_t i; if ((rval = emlxs_offline(hba))) { return (rval); } EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); - /* Save pci config space */ - ptr = (uint32_t *)hba->pm_config; - for (i = 0; i < PCI_CONFIG_SIZE; i += 4, ptr++) { - *ptr = - ddi_get32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + i)); - } - - /* Put chip in D3 state */ - (void) ddi_put8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), - (uint8_t)PCI_PM_D3_STATE); #ifdef FMA_SUPPORT if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) @@ -1825,24 +1839,7 @@ emlxs_power_up(emlxs_hba_t *hba) emlxs_port_t *port = &PPORT; #endif /* FMA_SUPPORT */ int32_t rval = 0; - uint32_t *ptr; - uint32_t i; - - /* Take chip out of D3 state */ - (void) ddi_put8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), - (uint8_t)PCI_PM_D0_STATE); - - /* Must have at least 10 ms delay here */ - DELAYMS(100); - - /* Restore pci config space */ - ptr = (uint32_t *)hba->pm_config; - for (i = 0; i < PCI_CONFIG_SIZE; i += 4, ptr++) { - (void) ddi_put32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + i), *ptr); - } #ifdef FMA_SUPPORT if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) @@ -1855,10 +1852,14 @@ emlxs_power_up(emlxs_hba_t *hba) /* Bring adapter online */ if ((rval = emlxs_online(hba))) { - (void) ddi_put8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + PCI_PM_CONTROL_REGISTER), - (uint8_t)PCI_PM_D3_STATE); - + if (hba->pci_cap_offset[PCI_CAP_ID_PM]) { + /* Put chip in D3 state */ + (void) ddi_put8(hba->pci_acc_handle, + (uint8_t *)(hba->pci_addr + + hba->pci_cap_offset[PCI_CAP_ID_PM] + + PCI_PMCSR), + (uint8_t)PCI_PMCSR_D3HOT); + } return (rval); } @@ -1895,12 +1896,7 @@ emlxs_ffcleanup(emlxs_hba_t *hba) port = &VPORT(i); if (port->node_count) { - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - (void) emlxs_sli4_unreg_all_rpi_by_port(port); - } else { - (void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, - 0); - } + (void) emlxs_mb_unreg_node(port, 0, 0, 0, 0); } } @@ -2009,7 +2005,7 @@ emlxs_unregister_pkt(CHANNEL *cp, uint16_t iotag, uint32_t forced) } if (sbp->bmp) { - (void) emlxs_mem_put(hba, MEM_BPL, (uint8_t *)sbp->bmp); + emlxs_mem_put(hba, MEM_BPL, (void *)sbp->bmp); sbp->bmp = 0; } @@ -2115,8 +2111,7 @@ emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { sbp = iocbq->sbp; if (sbp) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } } else { sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, @@ -2185,7 +2180,7 @@ emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) /* HBA is detaching or offlining */ if (icmd->ULPCOMMAND != CMD_QUE_RING_LIST64_CN) { - uint8_t *tmp; + void *tmp; RING *rp; rp = &hba->sli.sli3. @@ -2196,16 +2191,16 @@ emlxs_tx_channel_flush(emlxs_hba_t *hba, CHANNEL *cp, emlxs_buf_t *fpkt) mp = EMLXS_GET_VADDR( hba, rp, icmd); - tmp = (uint8_t *)mp; + tmp = (void *)mp; if (mp) { - (void) emlxs_mem_put( + emlxs_mem_put( hba, MEM_BUF, tmp); } } } - (void) emlxs_mem_put(hba, MEM_IOCB, - (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, + (void *)iocbq); } else { /* repost the unsolicited buffer */ EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, @@ -2363,8 +2358,7 @@ emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { sbp = iocbq->sbp; if (sbp) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } } else { sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, @@ -2434,7 +2428,7 @@ emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, /* HBA is detaching or offlining */ if (icmd->ULPCOMMAND != CMD_QUE_RING_LIST64_CN) { - uint8_t *tmp; + void *tmp; RING *rp; int ch; @@ -2447,16 +2441,16 @@ emlxs_tx_node_flush(emlxs_port_t *port, NODELIST *ndlp, CHANNEL *chan, mp = EMLXS_GET_VADDR( hba, rp, icmd); - tmp = (uint8_t *)mp; + tmp = (void *)mp; if (mp) { - (void) emlxs_mem_put( + emlxs_mem_put( hba, MEM_BUF, tmp); } } } - (void) emlxs_mem_put(hba, MEM_IOCB, - (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, + (void *)iocbq); } else { /* repost the unsolicited buffer */ EMLXS_SLI_ISSUE_IOCB_CMD(hba, @@ -2546,23 +2540,18 @@ emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, Q abort; uint32_t i; MATCHMAP *mp; - CHANNEL *cp; - CHANNEL *channel; uint8_t flag[MAX_CHANNEL]; + if (lun == EMLXS_LUN_NONE) { + return (0); + } + bzero((void *)&abort, sizeof (Q)); /* Flush I/O's on txQ to this target's lun */ mutex_enter(&EMLXS_TX_CHANNEL_LOCK); - channel = &hba->chan[hba->channel_fcp]; - for (channelno = 0; channelno < hba->chan_count; channelno++) { - cp = &hba->chan[channelno]; - - if (channel && cp != channel) { - continue; - } /* Scan the priority queue first */ prev = NULL; @@ -2673,8 +2662,7 @@ emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { sbp = iocbq->sbp; if (sbp) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } } else { sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, @@ -2744,7 +2732,7 @@ emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, /* HBA is detaching or offlining */ if (icmd->ULPCOMMAND != CMD_QUE_RING_LIST64_CN) { - uint8_t *tmp; + void *tmp; RING *rp; int ch; @@ -2757,16 +2745,16 @@ emlxs_tx_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint32_t lun, mp = EMLXS_GET_VADDR( hba, rp, icmd); - tmp = (uint8_t *)mp; + tmp = (void *)mp; if (mp) { - (void) emlxs_mem_put( + emlxs_mem_put( hba, MEM_BUF, tmp); } } } - (void) emlxs_mem_put(hba, MEM_IOCB, - (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, + (void *)iocbq); } else { /* repost the unsolicited buffer */ EMLXS_SLI_ISSUE_IOCB_CMD(hba, @@ -2839,8 +2827,7 @@ emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) mutex_exit(&sbp->mtx); if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } else { (void) emlxs_unregister_pkt(cp, sbp->iotag, 0); } @@ -2862,7 +2849,7 @@ emlxs_tx_put(IOCBQ *iocbq, uint32_t lock) mutex_exit(&EMLXS_TX_CHANNEL_LOCK); } - (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); } return; @@ -3333,8 +3320,7 @@ emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { sbp = iocbq->sbp; if (sbp) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } } else { sbp = emlxs_unregister_pkt((CHANNEL *)iocbq->channel, @@ -3399,7 +3385,7 @@ emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, /* HBA is detaching or offlining */ if (icmd->ULPCOMMAND != CMD_QUE_RING_LIST64_CN) { - uint8_t *tmp; + void *tmp; RING *rp; int ch; @@ -3412,9 +3398,9 @@ emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, mp = EMLXS_GET_VADDR( hba, rp, icmd); - tmp = (uint8_t *)mp; + tmp = (void *)mp; if (mp) { - (void) emlxs_mem_put( + emlxs_mem_put( hba, MEM_BUF, tmp); @@ -3423,8 +3409,8 @@ emlxs_tx_move(NODELIST *ndlp, CHANNEL *from_chan, CHANNEL *to_chan, } - (void) emlxs_mem_put(hba, MEM_IOCB, - (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, + (void *)iocbq); } else { /* repost the unsolicited buffer */ EMLXS_SLI_ISSUE_IOCB_CMD(hba, @@ -3563,6 +3549,22 @@ emlxs_iotag_flush(emlxs_hba_t *hba) continue; } + hba->fc_table[iotag] = STALE_PACKET; + hba->io_count--; + + /* Check if IO is valid */ + if (!(sbp->pkt_flags & PACKET_VALID) || + (sbp->pkt_flags & (PACKET_ULP_OWNED| + PACKET_COMPLETED|PACKET_IN_COMPLETION))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, + "iotag_flush: Invalid IO found. iotag=%x", + iotag); + + continue; + } + + sbp->iotag = 0; + /* Set IOCB status */ iocbq = &sbp->iocbq; iocb = &iocbq->iocb; @@ -3573,13 +3575,23 @@ emlxs_iotag_flush(emlxs_hba_t *hba) iocbq->next = NULL; if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); - } else { - hba->fc_table[iotag] = STALE_PACKET; - hba->io_count --; - sbp->iotag = 0; + if (sbp->xrip) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_sli_debug_msg, + "iotag_flush: iotag=%x sbp=%p " + "xrip=%p state=%x flag=%x", + iotag, sbp, sbp->xrip, + sbp->xrip->state, sbp->xrip->flag); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_sli_debug_msg, + "iotag_flush: iotag=%x sbp=%p " + "xrip=NULL", + iotag, sbp); + } + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 0); + } else { /* Clean up the sbp */ mutex_enter(&sbp->mtx); @@ -3593,8 +3605,8 @@ emlxs_iotag_flush(emlxs_hba_t *hba) } if (sbp->bmp) { - (void) emlxs_mem_put(hba, MEM_BPL, - (uint8_t *)sbp->bmp); + emlxs_mem_put(hba, MEM_BPL, + (void *)sbp->bmp); sbp->bmp = 0; } @@ -3635,8 +3647,8 @@ emlxs_iotag_flush(emlxs_hba_t *hba) emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "Forced iotag completion. channel=%d count=%d", + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, + "iotag_flush: channel=%d count=%d", channelno, abort.q_cnt); count += abort.q_cnt; @@ -3707,6 +3719,10 @@ emlxs_chipq_lun_flush(emlxs_port_t *port, NODELIST *ndlp, uint8_t flag[MAX_CHANNEL]; uint32_t channelno; + if (lun == EMLXS_LUN_NONE) { + return (0); + } + bzero((void *)flag, sizeof (flag)); bzero((void *)&abort, sizeof (Q)); @@ -3793,12 +3809,12 @@ emlxs_create_abort_xri_cn(emlxs_port_t *port, NODELIST *ndlp, sbp = hba->fc_table[iotag]; /* Try to issue abort by XRI if possible */ - if (sbp == NULL || sbp == STALE_PACKET || sbp->xp == NULL) { + if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { wqe->un.Abort.Criteria = ABORT_REQ_TAG; wqe->AbortTag = iotag; } else { wqe->un.Abort.Criteria = ABORT_XRI_TAG; - wqe->AbortTag = sbp->xp->XRI; + wqe->AbortTag = sbp->xrip->XRI; } wqe->un.Abort.IA = 0; wqe->RequestTag = abort_iotag; @@ -3912,12 +3928,12 @@ emlxs_create_close_xri_cn(emlxs_port_t *port, NODELIST *ndlp, sbp = hba->fc_table[iotag]; /* Try to issue close by XRI if possible */ - if (sbp == NULL || sbp == STALE_PACKET || sbp->xp == NULL) { + if (sbp == NULL || sbp == STALE_PACKET || sbp->xrip == NULL) { wqe->un.Abort.Criteria = ABORT_REQ_TAG; wqe->AbortTag = iotag; } else { wqe->un.Abort.Criteria = ABORT_XRI_TAG; - wqe->AbortTag = sbp->xp->XRI; + wqe->AbortTag = sbp->xrip->XRI; } wqe->un.Abort.IA = 1; wqe->RequestTag = abort_iotag; @@ -4011,7 +4027,7 @@ emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "Aborting FCT exchange: xid=%x", rxid); - if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { + if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { /* We have no way to abort unsolicited exchanges */ /* that we have not responded to at this time */ /* So we will return for now */ @@ -4047,6 +4063,47 @@ emlxs_abort_fct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) void +emlxs_close_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) +{ + CHANNEL *cp; + IOCBQ *iocbq; + IOCB *iocb; + + if (rxid == 0 || rxid == 0xFFFF) { + return; + } + + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "Closing ELS exchange: xid=%x", rxid); + + if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { + return; + } + } + + cp = &hba->chan[hba->channel_els]; + + mutex_enter(&EMLXS_FCTAB_LOCK); + + /* Create the abort IOCB */ + iocbq = emlxs_create_close_xri_cx(port, NULL, rxid, cp); + + mutex_exit(&EMLXS_FCTAB_LOCK); + + if (iocbq) { + iocb = &iocbq->iocb; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, + "Closing ELS exchange: xid=%x iotag=%x", rxid, + iocb->ULPIOTAG); + + EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); + } + +} /* emlxs_close_els_exchange() */ + + +void emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) { CHANNEL *cp; @@ -4062,7 +4119,7 @@ emlxs_abort_els_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, "Aborting ELS exchange: xid=%x", rxid); - if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { + if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { /* We have no way to abort unsolicited exchanges */ /* that we have not responded to at this time */ /* So we will return for now */ @@ -4111,7 +4168,7 @@ emlxs_abort_ct_exchange(emlxs_hba_t *hba, emlxs_port_t *port, uint32_t rxid) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_ct_msg, "Aborting CT exchange: xid=%x", rxid); - if (emlxs_sli4_unreserve_xri(hba, rxid) == 0) { + if (emlxs_sli4_unreserve_xri(hba, rxid, 1) == 0) { /* We have no way to abort unsolicited exchanges */ /* that we have not responded to at this time */ /* So we will return for now */ @@ -4159,8 +4216,12 @@ emlxs_sbp_abort_add(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abort, ndlp = sbp->node; /* Create the close XRI IOCB */ - iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); - + if (hba->state >= FC_LINK_UP) { + iocbq = emlxs_create_abort_xri_cn(port, ndlp, sbp->iotag, cp, + CLASS3, ABORT_TYPE_ABTS); + } else { + iocbq = emlxs_create_close_xri_cn(port, ndlp, sbp->iotag, cp); + } /* * Add this iocb to our local abort Q * This way we don't hold the CHIPQ lock too long diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c index 1556746b9c..34759c121c 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c @@ -40,12 +40,8 @@ static fct_status_t emlxs_fct_cmd_accept(emlxs_port_t *port, static void emlxs_fct_cmd_release(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state); -static void emlxs_fct_handle_acc(emlxs_port_t *port, emlxs_buf_t *sbp, - IOCBQ *iocbq); -static void emlxs_fct_handle_reject(emlxs_port_t *port, emlxs_buf_t *sbp, - IOCBQ *iocbq); static emlxs_buf_t *emlxs_fct_cmd_init(emlxs_port_t *port, - fct_cmd_t *fct_cmd, uint32_t fct_state); + fct_cmd_t *fct_cmd, uint16_t fct_state); static void emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state); static void emlxs_fct_cmd_post(emlxs_port_t *port, fct_cmd_t *fct_cmd, @@ -996,7 +992,7 @@ emlxs_fct_cfg_init(emlxs_hba_t *hba) KM_SLEEP); mutex_init(&port->iotrace_mtx, NULL, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); emlxs_iotrace = (uint8_t *)port->iotrace; emlxs_iotrace_cnt = port->iotrace_cnt; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, @@ -1159,12 +1155,7 @@ emlxs_fct_unbind_port(emlxs_port_t *port) /* Destroy & flush all port nodes, if they exist */ if (port->node_count) { - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - (void) emlxs_sli4_unreg_all_rpi_by_port(port); - } else { - (void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, - 0); - } + (void) emlxs_mb_unreg_node(port, NULL, NULL, NULL, NULL); } port->flag &= ~EMLXS_PORT_BOUND; @@ -1532,7 +1523,7 @@ emlxs_fct_port_info(uint32_t cmd, fct_local_port_t *fct_port, void *arg, mb->un.varRdLnk.crcCnt; } - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); break; default: @@ -1722,11 +1713,21 @@ emlxs_fct_ctl(fct_local_port_t *fct_port, int cmd, void *arg) break; case FCT_CMD_FORCE_LIP: - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, - "emlxs_fct_ctl: FCT_CMD_FORCE_LIP"); + if (hba->fw_flag & FW_UPDATE_NEEDED) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, + "emlxs_fct_ctl: FCT_CMD_FORCE_LIP -> " + "FCT_CMD_RESET"); + + hba->fw_flag |= FW_UPDATE_KERNEL; + /* Reset the adapter */ + (void) emlxs_reset(port, FC_FCA_RESET); + } else { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, + "emlxs_fct_ctl: FCT_CMD_FORCE_LIP"); - /* Reset the link */ - (void) emlxs_reset(port, FC_FCA_LINK_RESET); + /* Reset the link */ + (void) emlxs_reset(port, FC_FCA_LINK_RESET); + } break; } @@ -2181,6 +2182,8 @@ emlxs_fct_register_remote_port(fct_local_port_t *fct_port, /* mutex_enter(&cmd_sbp->fct_mtx); */ } + cmd_sbp->fct_flags &= ~EMLXS_FCT_REGISTERED; + if (!cmd_sbp->node) { cmd_sbp->node = emlxs_node_find_did(port, fct_cmd->cmd_rportid); @@ -2239,7 +2242,7 @@ emlxs_fct_register_remote_port(fct_local_port_t *fct_port, pkt_ret = 0; while ((pkt_ret != -1) && (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) && - (cmd_sbp->node == NULL)) { + !(cmd_sbp->fct_flags & EMLXS_FCT_REGISTERED)) { pkt_ret = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout); } @@ -2265,6 +2268,8 @@ done: ndlp = (emlxs_node_t *)cmd_sbp->node; if (ndlp) { + cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED; + *((emlxs_node_t **)remote_port->rp_fca_private) = cmd_sbp->node; remote_port->rp_handle = ndlp->nlp_Rpi; @@ -2305,6 +2310,7 @@ emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port, fct_remote_port_t *remote_port) { emlxs_port_t *port = (emlxs_port_t *)fct_port->port_fca_private; + emlxs_node_t *ndlp; #ifdef FCT_API_TRACE EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, @@ -2316,8 +2322,13 @@ emlxs_fct_deregister_remote_port(fct_local_port_t *fct_port, remote_port->rp_id, remote_port->rp_handle); #endif /* FCT_API_TRACE */ + ndlp = *((emlxs_node_t **)remote_port->rp_fca_private); *((emlxs_node_t **)remote_port->rp_fca_private) = NULL; - (void) emlxs_mb_unreg_did(port, remote_port->rp_id, NULL, NULL, NULL); + + if (ndlp) { + (void) emlxs_mb_unreg_node(port, ndlp, NULL, + NULL, NULL); + } TGTPORTSTAT.FctPortDeregister++; return (FCT_SUCCESS); @@ -3237,7 +3248,7 @@ emlxs_fct_handle_unsol_els(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, sizeof (emlxs_iocb_t)); els = (fct_els_t *)fct_cmd->cmd_specific; - els->els_req_size = size; + els->els_req_size = (uint16_t)size; els->els_req_payload = GET_BYTE_OFFSET(fct_cmd->cmd_fca_private, GET_STRUCT_SIZE(emlxs_buf_t)); @@ -3385,15 +3396,16 @@ emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, /* Mutex will be acquired */ static emlxs_buf_t * -emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint32_t fct_state) +emlxs_fct_cmd_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) { emlxs_hba_t *hba = HBA; emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; bzero((void *)cmd_sbp, sizeof (emlxs_buf_t)); mutex_init(&cmd_sbp->fct_mtx, NULL, MUTEX_DRIVER, - (void *)hba->intr_arg); - mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); + mutex_init(&cmd_sbp->mtx, NULL, MUTEX_DRIVER, + DDI_INTR_PRI(hba->intr_arg)); mutex_enter(&cmd_sbp->fct_mtx); cmd_sbp->pkt_flags = PACKET_VALID; @@ -3663,8 +3675,8 @@ emlxs_fct_cmd_done(emlxs_port_t *port, fct_cmd_t *fct_cmd, uint16_t fct_state) if (cmd_sbp->channel) { if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[cmd_sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, cmd_sbp, cmd_sbp->xp); + emlxs_sli4_free_xri(hba, cmd_sbp, cmd_sbp->xrip, + 1); } else { (void) emlxs_unregister_pkt(cmd_sbp->channel, cmd_sbp->iotag, 0); @@ -4347,8 +4359,7 @@ emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp) /* The IOCB points to iocb_sbp (no packet) or a sbp (packet) */ if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[iocb_sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, iocb_sbp, iocb_sbp->xp); + emlxs_sli4_free_xri(hba, iocb_sbp, iocb_sbp->xrip, 1); } else { (void) emlxs_unregister_pkt(cp, iocb_sbp->iotag, 0); } @@ -4799,7 +4810,7 @@ emlxs_fct_dmem_init(emlxs_port_t *port) (void) sprintf(buf, "%s%d_bucket%d mutex", DRIVER_NAME, hba->ddiinst, i); mutex_init(&p->dmem_lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg, "bufsize=%d cnt=%d", p->dmem_buf_size, p->dmem_nbufs); diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c index 24d7b05060..f86f42fe1b 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -33,11 +33,12 @@ /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ EMLXS_MSG_DEF(EMLXS_HBA_C); -static uint32_t emlxs_decode_biu_rev(uint32_t rev); -static uint32_t emlxs_decode_endec_rev(uint32_t rev); + static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq); +static void emlxs_pci_cap_offsets(emlxs_hba_t *hba); + #ifdef MSI_SUPPORT uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; @@ -49,6 +50,29 @@ uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE; int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t); +emlxs_table_t emlxs_pci_cap[] = { + {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"}, + {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"}, + {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"}, + {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"}, + {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"}, + {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"}, + {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"}, + {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"}, + {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"}, + {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"}, + {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"}, + {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"}, + {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"}, + {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"}, + {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"}, + {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"}, + {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"}, + {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"}, + {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"} + +}; /* emlxs_pci_cap */ + emlxs_table_t emlxs_ring_table[] = { {FC_FCP_RING, "FCP Ring"}, {FC_IP_RING, "IP Ring"}, @@ -57,7 +81,6 @@ emlxs_table_t emlxs_ring_table[] = { }; /* emlxs_ring_table */ - emlxs_table_t emlxs_ffstate_table[] = { {0, "NULL"}, {FC_ERROR, "ERROR"}, @@ -249,6 +272,7 @@ initialize: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "MSI: Unable to allocate interrupts. error=%d", ret); + actual = 0; goto init_failed; } @@ -383,7 +407,7 @@ initialize: (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, hba->ddiinst, i); mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); } /* Set flag to indicate support */ @@ -394,7 +418,7 @@ initialize: (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, hba->ddiinst, i); mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); emlxs_thread_create(hba, &hba->chan[i].intr_thread); } @@ -792,7 +816,7 @@ emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, hba->ddiinst, i); mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); emlxs_thread_create(hba, &hba->chan[i].intr_thread); } @@ -1257,21 +1281,6 @@ emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size) } /* emlxs_parse_fcoe */ - -static uint32_t -emlxs_decode_biu_rev(uint32_t rev) -{ - return (rev & 0xf); -} /* End emlxs_decode_biu_rev */ - - -static uint32_t -emlxs_decode_endec_rev(uint32_t rev) -{ - return ((rev >> 28) & 0xf); -} /* End emlxs_decode_endec_rev */ - - extern void emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) { @@ -2018,78 +2027,22 @@ emlxs_init_adapter_info(emlxs_hba_t *hba) } #endif /* !SATURN_MSI_SUPPORT */ + /* Scan the PCI capabilities */ + emlxs_pci_cap_offsets(hba); #ifdef MSI_SUPPORT /* Verify MSI support */ - if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { - uint32_t offset; - uint32_t reg; - - /* Scan for MSI capabilities register */ - offset = - ddi_get32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); - offset &= 0xff; - - while (offset) { - reg = - ddi_get32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + offset)); - - if ((reg & 0xff) == MSI_CAP_ID) { - break; - } - offset = (reg >> 8) & 0xff; - } - - if (offset) { - hba->msi_cap_offset = offset + 2; - } else { - hba->msi_cap_offset = 0; - hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; - - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_debug_msg, - "MSI: control_reg capability not found!"); - } + if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) && + !hba->pci_cap_offset[PCI_CAP_ID_MSI]) { + hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; } /* Verify MSI-X support */ - if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { - uint32_t offset; - uint32_t reg; - - /* Scan for MSI capabilities register */ - offset = - ddi_get32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); - offset &= 0xff; - - while (offset) { - reg = - ddi_get32(hba->pci_acc_handle, - (uint32_t *)(hba->pci_addr + offset)); - - if ((reg & 0xff) == MSIX_CAP_ID) { - break; - } - offset = (reg >> 8) & 0xff; - } - - if (offset) { - hba->msix_cap_offset = offset; - } else { - hba->msix_cap_offset = 0; - hba->model_info.flags &= - ~EMLXS_MSIX_SUPPORTED; - - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_debug_msg, - "MSIX: control_reg capability not found!"); - } + if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) && + !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) { + hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED; } #endif /* MSI_SUPPORT */ - } if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0, @@ -2308,7 +2261,7 @@ emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) iocb = &iocbq->iocb; #ifdef DEBUG_CMPL_IOCB - emlxs_data_dump(hba, "CMPL_IOCB", (uint32_t *)iocb, 8, 0); + emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0); #endif sbp = (emlxs_buf_t *)iocbq->sbp; @@ -2616,6 +2569,25 @@ emlxs_ring_xlate(uint32_t ringno) } /* emlxs_ring_xlate() */ +extern char * +emlxs_pci_cap_xlate(uint32_t id) +{ + static char buffer[32]; + uint32_t i; + uint32_t count; + + count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t); + for (i = 0; i < count; i++) { + if (id == emlxs_pci_cap[i].code) { + return (emlxs_pci_cap[i].string); + } + } + + (void) sprintf(buffer, "PCI_CAP_ID_%02X", id); + return (buffer); + +} /* emlxs_pci_cap_xlate() */ + extern void emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) @@ -2683,7 +2655,7 @@ xlate: } } - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); return; @@ -2826,3 +2798,41 @@ emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) } /* emlxs_fw_unload() */ #endif /* MODFW_SUPPORT */ + + +static void +emlxs_pci_cap_offsets(emlxs_hba_t *hba) +{ + emlxs_port_t *port = &PPORT; + uint8_t offset; + uint8_t id; + + bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset)); + + /* Read first offset */ + offset = ddi_get8(hba->pci_acc_handle, + (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER)); + offset &= PCI_CAP_PTR_MASK; + + while (offset >= PCI_CAP_PTR_OFF) { + /* Read the next cap id */ + id = ddi_get8(hba->pci_acc_handle, + (uint8_t *)(hba->pci_addr + offset)); + + if (id < PCI_CAP_MAX_PTR) { + hba->pci_cap_offset[id] = offset; + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, + "%s: offset=0x%x", + emlxs_pci_cap_xlate(id), offset); + + /* Read next offset */ + offset = ddi_get8(hba->pci_acc_handle, + (uint8_t *)(hba->pci_addr + offset + PCI_CAP_NEXT_PTR)); + offset &= PCI_CAP_PTR_MASK; + } + + return; + +} /* emlxs_pci_cap_offsets() */ diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_ip.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_ip.c index 95b8a47b26..d68401be42 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_ip.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_ip.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -252,7 +252,7 @@ emlxs_ip_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq, "Node not found. mac=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - (void) emlxs_ub_release((opaque_t)port, 1, + (void) emlxs_fca_ub_release((opaque_t)port, 1, &ubp->ub_token); continue; @@ -360,7 +360,7 @@ out: emlxs_update_HBQ_index(hba, hbq_id); } else { if (mp) { - (void) emlxs_mem_put(hba, MEM_IPBUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_IPBUF, (void *)mp); } (void) emlxs_post_buffer(hba, rp, 1); } diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c index f23103cb4a..0198b631a3 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -30,13 +30,6 @@ /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ EMLXS_MSG_DEF(EMLXS_MBOX_C); -static void emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq, - uint32_t hbainit); -static void emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq, - uint32_t mask, uint32_t ringno); -static void emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq, - uint32_t word0, uint32_t word1, uint32_t word2); -static void emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq); emlxs_table_t emlxs_mb_cmd_table[] = { @@ -60,7 +53,7 @@ emlxs_table_t emlxs_mb_cmd_table[] = { {MBX_READ_REV, "READ_REV"}, {MBX_READ_LNK_STAT, "READ_LNK_STAT"}, {MBX_REG_LOGIN, "REG_LOGIN"}, - {MBX_UNREG_LOGIN, "UNREG_LOGIN"}, + {MBX_UNREG_LOGIN, "UNREG_RPI"}, {MBX_READ_LA, "READ_LA"}, {MBX_CLEAR_LA, "CLEAR_LA"}, {MBX_DUMP_MEMORY, "DUMP_MEMORY"}, @@ -83,7 +76,7 @@ emlxs_table_t emlxs_mb_cmd_table[] = { {MBX_READ_RPI64, "READ_RPI64"}, {MBX_CONFIG_MSI, "CONFIG_MSI"}, {MBX_CONFIG_MSIX, "CONFIG_MSIX"}, - {MBX_REG_LOGIN64, "REG_LOGIN64"}, + {MBX_REG_LOGIN64, "REG_RPI"}, {MBX_READ_LA64, "READ_LA64"}, {MBX_FLASH_WR_ULA, "FLASH_WR_ULA"}, {MBX_SET_DEBUG, "SET_DEBUG"}, @@ -114,131 +107,94 @@ emlxs_table_t emlxs_mb_cmd_table[] = { }; /* emlxs_mb_cmd_table */ -/* - * emlxs_mb_resetport Issue a Port Reset mailbox command - */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_resetport(emlxs_hba_t *hba, MAILBOXQ *mbq) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_COMMON; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_RESET; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_RESET; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0; return; } /* emlxs_mb_resetport() */ -/* - * emlxs_mb_request_features Issue a REQUEST FEATURES mailbox command - */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_request_features(emlxs_hba_t *hba, MAILBOXQ *mbq) { emlxs_config_t *cfg = &CFG; - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; hba->flag &= ~FC_NPIV_ENABLED; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; - mb->mbxCommand = MBX_REQUEST_FEATURES; - mb->mbxOwner = OWN_HOST; - mb->un.varReqFeatures.featuresRequested |= + mb4->mbxCommand = MBX_REQUEST_FEATURES; + mb4->mbxOwner = OWN_HOST; + mb4->un.varReqFeatures.featuresRequested |= SLI4_FEATURE_FCP_INITIATOR; if (cfg[CFG_NPIV_ENABLE].current) { - mb->un.varReqFeatures.featuresRequested |= + mb4->un.varReqFeatures.featuresRequested |= SLI4_FEATURE_NPIV; } } /* emlxs_mb_request_features() */ -/* - * emlxs_mb_resume_rpi Issue a RESUME_RPI mailbox command - */ -/*ARGSUSED*/ -extern int -emlxs_mb_resume_rpi(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t rpi) -{ - MAILBOX4 *mb; - MAILBOXQ *mbq; - uint32_t rval; - - (void) emlxs_sli4_find_rpi(hba, rpi); - - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - return (1); - } - mb = (MAILBOX4 *)mbq; - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - mbq->nonembed = NULL; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - mbq->sbp = (uint8_t *)sbp; - - mb->mbxCommand = MBX_RESUME_RPI; - mb->mbxOwner = OWN_HOST; - mb->un.varResumeRPI.EventTag = hba->link_event_tag; - mb->un.varResumeRPI.RPI = rpi; - - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } - return (rval); - -} /* emlxs_mb_resume_rpi() */ - - +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_COMMON_NOP *nop; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_NOP) + + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_NOP) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_COMMON; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_NOP; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_NOP; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_COMMON_NOP); - nop = (IOCTL_COMMON_NOP *)&mb->un.varSLIConfig.payload; + nop = (IOCTL_COMMON_NOP *)&mb4->un.varSLIConfig.payload; nop->params.request.context = -1; return; @@ -246,16 +202,17 @@ emlxs_mb_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) } /* emlxs_mb_noop() */ +/* SLI4 */ /*ARGSUSED*/ extern int emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_COMMON_NOP *nop; MATCHMAP *mp; mbox_req_hdr_t *hdr_req; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { return (1); @@ -264,12 +221,13 @@ emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) * Save address for completion * Signifies a non-embedded command */ - mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; + mb4->un.varSLIConfig.be.embedded = 0; + mbq->nonembed = (void *)mp; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; hdr_req = (mbox_req_hdr_t *)mp->virt; hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; @@ -284,325 +242,36 @@ emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq) } /* emlxs_mbext_noop() */ -int -emlxs_cmpl_read_fcf_table(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - mbox_rsp_hdr_t *hdr_rsp; - IOCTL_FCOE_READ_FCF_TABLE *fcf; - FCF_RECORD_t *fcfrec; - FCFIobj_t *fcfp; - MAILBOX4 *mb; - MATCHMAP *mp; - MAILBOXQ *fcfmbq; - uint32_t i, *iptr; - uint16_t s, *sptr; - int rc; - - mb = (MAILBOX4 *)mbq; - mp = (MATCHMAP *)mbq->nonembed; - hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL read fcf: stats: %x %x %x", - mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status); - - if (mb->mbxStatus || hdr_rsp->status) { - /* Wait for FCF found async event */ - return (0); - } - - /* - * Only support 1 FCF for now, so we don't need to walk - * thru the FCF table. - */ - fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1); - fcfrec = &fcf->params.response.fcf_entry[0]; - - /* Fix up data in FCF record */ - BE_SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8); - BE_SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8); - BE_SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512); - iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0]; - i = *iptr; - *iptr = BE_SWAP32(i); - sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0]; - s = *sptr; - *sptr = BE_SWAP16(s); -#ifdef EMLXS_BIG_ENDIAN - i = fcfrec->fc_map[0]; - fcfrec->fc_map[0] = fcfrec->fc_map[2]; - fcfrec->fc_map[2] = i; -#endif - - /* Assign a FCFI object for the fcf_index */ - fcfp = emlxs_sli4_assign_fcfi(hba, fcfrec); - if (!fcfp) { - return (0); - } - fcfp->EventTag = fcf->params.response.event_tag; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL read fcf: info: x%x x%x", - fcfp->EventTag, fcf->params.response.next_valid_fcf_index); - - if (emlxs_sli4_bind_fcfi(hba)) { - /* - * In this phase, if we successfully bind to just - * 1 FCFI we are done. - */ - return (0); - } - - if (fcf->params.response.next_valid_fcf_index == 0xffff) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Waiting for a valid FCF to be discovered"); - return (0); - } - - /* Get the next one */ - if (!(fcfmbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - return (0); - } - rc = emlxs_mbext_read_fcf_table(hba, fcfmbq, - fcf->params.response.next_valid_fcf_index); - if (rc == 0) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq); - return (0); - } - - rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, fcfmbq, MBX_NOWAIT, 0); - if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq); - } - return (0); -} /* emlxs_cmpl_read_fcf_table() */ - - -extern int -emlxs_mbext_read_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) -{ - MAILBOX4 *mb = (MAILBOX4 *)mbq; - IOCTL_FCOE_READ_FCF_TABLE *fcf; - MATCHMAP *mp; - mbox_req_hdr_t *hdr_req; - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { - return (0); - } - /* - * Save address for completion - * Signifies a non-embedded command - */ - mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; - mbq->mbox_cmpl = emlxs_cmpl_read_fcf_table; - - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - - hdr_req = (mbox_req_hdr_t *)mp->virt; - hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; - hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE; - hdr_req->timeout = 0; - hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE); - fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1); - fcf->params.request.fcf_index = index; - - return (1); - -} /* emlxs_mbext_read_fcf_table() */ - - -int -emlxs_cmpl_add_fcf_table(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - MAILBOX4 *mb; - MAILBOXQ *mq; - MATCHMAP *mp; - mbox_rsp_hdr_t *hdr_rsp; - uint32_t rc; - - mb = (MAILBOX4 *)mbq; - mp = (MATCHMAP *)mbq->nonembed; - - hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL add fcf: stats: %x %x %x", - mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status); - - if (mbq->nonembed) { - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbq->nonembed); - mbq->nonembed = 0; - } - - if (mb->mbxStatus) { - /* In nonFIP mode, FCF Entries are persistent */ - if (!hdr_rsp->status || - (hdr_rsp->status != MGMT_STATUS_FCF_IN_USE)) { - return (0); - } - } - - /* - * Now that we have a fcf table entry, read it back - * to fall into the normal link up processing. - */ - if (!(mq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL add fcf: Cannot alloc mbox"); - return (0); - } - rc = emlxs_mbext_read_fcf_table(hba, mq, -1); - - if (rc == 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL add fcf: Cannot build read fcf mbox"); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq); - return (0); - } - - rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mq, MBX_NOWAIT, 0); - if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL add fcf: Cannot issue read fcf mbox"); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq); - } - return (0); -} /* emlxs_cmpl_add_fcf_table() */ - - -extern int -emlxs_mbext_add_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) -{ - emlxs_port_t *port = &PPORT; - MAILBOX4 *mb = (MAILBOX4 *)mbq; - IOCTL_FCOE_ADD_FCF_TABLE *fcf; - FCF_RECORD_t *fcfrec; - MATCHMAP *mp; - mbox_req_hdr_t *hdr_req; - uint16_t i; - uint8_t bitmap[512]; - - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { - return (0); - } - /* - * Save address for completion - * Signifies a non-embedded command - */ - mb->un.varSLIConfig.be.embedded = 0; - mbq->nonembed = (uint8_t *)mp; - mbq->mbox_cmpl = emlxs_cmpl_add_fcf_table; - - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - - hdr_req = (mbox_req_hdr_t *)mp->virt; - hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE; - hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE; - hdr_req->timeout = 0; - hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE); - fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1); - fcf->params.request.fcf_index = index; - - fcfrec = &fcf->params.request.fcf_entry; - fcfrec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ; - fcfrec->fka_adv_period = 0; - fcfrec->fip_priority = 128; -#ifdef EMLXS_BIG_ENDIAN - fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3; - fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2; - fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1; - fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0; - fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC5; - fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC4; - fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2]; - fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; - fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0]; -#endif -#ifdef EMLXS_LITTLE_ENDIAN - fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0; - fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1; - fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2; - fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3; - fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC4; - fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC5; - fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0]; - fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1]; - fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2]; -#endif - - if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) { - bzero((void *) bitmap, 512); - i = hba->sli.sli4.cfgFCOE.VLanId; - bitmap[i / 8] = (1 << (i % 8)); - BE_SWAP32_BCOPY(bitmap, fcfrec->vlan_bitmap, 512); - } else { - bzero((void *) bitmap, 512); - bitmap[0] = 1; /* represents bit 0 */ - BE_SWAP32_BCOPY(bitmap, fcfrec->vlan_bitmap, 512); - } - - fcfrec->fcf_valid = 1; - fcfrec->fcf_available = 1; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "ADD FCF %d: av: %x %x ste %x macp %x " - "addr: %02x:%02x:%02x:%02x:%02x:%02x", - fcfrec->fcf_index, - fcfrec->fcf_available, - fcfrec->fcf_valid, - fcfrec->fcf_state, - fcfrec->mac_address_provider, - fcfrec->fcf_mac_address_hi[0], - fcfrec->fcf_mac_address_hi[1], - fcfrec->fcf_mac_address_hi[2], - fcfrec->fcf_mac_address_hi[3], - fcfrec->fcf_mac_address_low[0], - fcfrec->fcf_mac_address_low[1]); - return (1); - -} /* emlxs_mbext_add_fcf_table() */ - - +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_eq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_COMMON_EQ_CREATE *qp; uint64_t addr; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_EQ_CREATE) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_COMMON; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_EQ_CREATE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_EQ_CREATE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_COMMON_EQ_CREATE); - qp = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload; + qp = (IOCTL_COMMON_EQ_CREATE *)&mb4->un.varSLIConfig.payload; /* 1024 * 4 bytes = 4K */ qp->params.request.EQContext.Count = EQ_ELEMENT_COUNT_1024; @@ -620,34 +289,36 @@ emlxs_mb_eq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) } /* emlxs_mb_eq_create() */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_cq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_COMMON_CQ_CREATE *qp; uint64_t addr; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_CQ_CREATE) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_COMMON; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_CQ_CREATE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_CQ_CREATE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_COMMON_CQ_CREATE); - qp = (IOCTL_COMMON_CQ_CREATE *)&mb->un.varSLIConfig.payload; + qp = (IOCTL_COMMON_CQ_CREATE *)&mb4->un.varSLIConfig.payload; /* 256 * 16 bytes = 4K */ qp->params.request.CQContext.Count = CQ_ELEMENT_COUNT_256; @@ -666,37 +337,39 @@ emlxs_mb_cq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) } /* emlxs_mb_cq_create() */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_wq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_FCOE_WQ_CREATE *qp; uint64_t addr; int i; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_FCOE_WQ_CREATE) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_FCOE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_WQ_CREATE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_WQ_CREATE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_FCOE_WQ_CREATE); addr = hba->sli.sli4.wq[num].addr.phys; - qp = (IOCTL_FCOE_WQ_CREATE *)&mb->un.varSLIConfig.payload; + qp = (IOCTL_FCOE_WQ_CREATE *)&mb4->un.varSLIConfig.payload; qp->params.request.CQId = hba->sli.sli4.wq[num].cqid; @@ -712,36 +385,38 @@ emlxs_mb_wq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) } /* emlxs_mb_wq_create() */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_rq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_FCOE_RQ_CREATE *qp; uint64_t addr; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_FCOE_RQ_CREATE) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_FCOE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_RQ_CREATE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_RQ_CREATE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_FCOE_RQ_CREATE); addr = hba->sli.sli4.rq[num].addr.phys; - qp = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload; + qp = (IOCTL_FCOE_RQ_CREATE *)&mb4->un.varSLIConfig.payload; qp->params.request.RQContext.RQSize = RQ_DEPTH_EXPONENT; qp->params.request.RQContext.BufferSize = RQB_DATA_SIZE; @@ -756,36 +431,38 @@ emlxs_mb_rq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num) } /* emlxs_mb_rq_create() */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_mq_create(emlxs_hba_t *hba, MAILBOXQ *mbq) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; IOCTL_COMMON_MQ_CREATE *qp; uint64_t addr; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* * Signifies an embedded command */ - mb->un.varSLIConfig.be.embedded = 1; + mb4->un.varSLIConfig.be.embedded = 1; - mb->mbxCommand = MBX_SLI_CONFIG; - mb->mbxOwner = OWN_HOST; - mb->un.varSLIConfig.be.payload_length = + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ; - mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = IOCTL_SUBSYSTEM_COMMON; - mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_MQ_CREATE; - mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; - mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_MQ_CREATE; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = sizeof (IOCTL_COMMON_MQ_CREATE); addr = hba->sli.sli4.mq.addr.phys; - qp = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload; + qp = (IOCTL_COMMON_MQ_CREATE *)&mb4->un.varSLIConfig.payload; qp->params.request.MQContext.Size = MQ_ELEMENT_COUNT_16; qp->params.request.MQContext.Valid = 1; @@ -800,456 +477,53 @@ emlxs_mb_mq_create(emlxs_hba_t *hba, MAILBOXQ *mbq) } /* emlxs_mb_mq_create() */ -static int -emlxs_cmpl_reg_fcfi(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - FCFIobj_t *fcfp; - VFIobj_t *vfip; - RPIobj_t *rpip; - MAILBOX4 *mb; - - mb = (MAILBOX4 *)mbq; - fcfp = (FCFIobj_t *)mbq->context; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL reg fcfi: status: %x", mb->mbxStatus); - - if (mb->mbxStatus) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to register FCFI for FCFI %d index %d", - mb->un.varRegFCFI.FCFI, mb->un.varRegFCFI.InfoIndex); - (void) emlxs_sli4_free_fcfi(hba, fcfp); - return (0); - } - - fcfp->state |= RESOURCE_FCFI_REG; - - if (!fcfp->fcf_vfi) { - vfip = emlxs_sli4_alloc_vfi(hba, fcfp); - if (!vfip) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to alloc VFI for Fabric, fcf index %d", - fcfp->FCF_index); - (void) emlxs_sli4_free_fcfi(hba, fcfp); - return (0); - } - fcfp->fcf_vfi = vfip; - } - - if (!fcfp->fcf_vpi) { - fcfp->fcf_vpi = port; - port->VFIp = fcfp->fcf_vfi; - port->VFIp->outstandingVPIs++; - } - - rpip = &fcfp->scratch_rpi; - rpip->state = RESOURCE_ALLOCATED; - rpip->VPIp = fcfp->fcf_vpi; - rpip->RPI = 0xffff; - rpip->index = 0xffff; - - fcfp->FCFI = mb->un.varRegFCFI.FCFI; - - /* Declare the linkup here */ - if (!(fcfp->state & RESOURCE_FCFI_DISC)) { - fcfp->state |= RESOURCE_FCFI_DISC; - emlxs_linkup(hba); - } - return (0); - -} /* emlxs_cmpl_reg_fcfi() */ - - -/*ARGSUSED*/ -extern void -emlxs_mb_reg_fcfi(emlxs_hba_t *hba, MAILBOXQ *mbq, FCFIobj_t *fcfp) -{ - MAILBOX4 *mb = (MAILBOX4 *)mbq; - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - mb->mbxCommand = MBX_REG_FCFI; - mb->mbxOwner = OWN_HOST; - mb->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */ - mb->un.varRegFCFI.InfoIndex = fcfp->FCF_index; - - mb->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid; - mb->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK; - mb->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL; - mb->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK; - mb->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE; - - mb->un.varRegFCFI.RQId1 = 0xffff; - mb->un.varRegFCFI.RQId2 = 0xffff; - mb->un.varRegFCFI.RQId3 = 0xffff; - - if (fcfp->state & RESOURCE_FCFI_VLAN_ID) { - mb->un.varRegFCFI.vv = 1; - mb->un.varRegFCFI.vlanTag = fcfp->vlan_id; - } - - /* Ignore the fcf record and force FPMA */ - mb->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA; - - mbq->mbox_cmpl = emlxs_cmpl_reg_fcfi; - mbq->context = (uint8_t *)fcfp; - return; - -} /* emlxs_mb_reg_fcfi() */ - - /* SLI4 */ -static int -emlxs_cmpl_unreg_fcfi(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - FCFIobj_t *fcfp; - MAILBOX4 *mb; - - mb = (MAILBOX4 *)mbq; - fcfp = (FCFIobj_t *)mbq->context; - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL unreg fcfi: status: %x", mb->mbxStatus); - - if (mb->mbxStatus) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to unregister FCFI %d index %d", - fcfp->FCFI, fcfp->FCF_index); - } - - (void) emlxs_sli4_free_fcfi(hba, fcfp); - - /* Make sure link is declared down */ - emlxs_linkdown(hba); - - return (0); - -} /* emlxs_cmpl_unreg_fcfi() */ - - -/* ARGSUSED */ -extern int -emlxs_mb_unreg_fcfi(emlxs_hba_t *hba, FCFIobj_t *fcfp) -{ - MAILBOXQ *mbq; - MAILBOX4 *mb; - uint32_t rval; - - mutex_enter(&EMLXS_PORT_LOCK); - - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - mutex_exit(&EMLXS_PORT_LOCK); - return (1); - } - mb = (MAILBOX4 *)mbq; - mutex_exit(&EMLXS_PORT_LOCK); - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - mb->mbxCommand = MBX_UNREG_FCFI; - mb->mbxOwner = OWN_HOST; - mb->un.varUnRegFCFI.FCFI = fcfp->FCFI; - - mbq->mbox_cmpl = emlxs_cmpl_unreg_fcfi; - mbq->context = (uint8_t *)fcfp; - fcfp->fcf_vfi = NULL; - fcfp->fcf_vpi = NULL; - - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } - - return (0); - -} /* emlxs_mb_unreg_fcfi() */ - - -int -emlxs_mb_cmpl_reg_vfi(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - MAILBOX4 *mb; - MAILBOXQ *mbox; - MATCHMAP *mp; - NODELIST *ndlp; - emlxs_port_t *vport; - VFIobj_t *vfip; - uint8_t *wwn; - volatile SERV_PARM *sp; - int32_t i; - uint32_t ldid; - emlxs_vvl_fmt_t vvl; - - mb = (MAILBOX4 *)mbq; - if (mb->mbxStatus) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_sli_detail_msg, - "REG_VFI failed. status=x%x", mb->mbxStatus); - return (0); - } - - vport = (emlxs_port_t *)mbq->context; - vfip = vport->VFIp; - vfip->state |= RESOURCE_VFI_REG; - - if (mb->un.varRegVFI4.vp) { - vport->flag |= EMLXS_PORT_REGISTERED; - } - - mp = (MATCHMAP *)mbq->bp; - if (!mp) { - return (0); - } - sp = (volatile SERV_PARM *)mp->virt; - - ldid = FABRIC_DID; - ndlp = emlxs_node_find_did(port, ldid); - - if (!ndlp) { - /* Attempt to create a node */ - if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { - ndlp->nlp_Rpi = 0xffff; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, - sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, - sizeof (NAME_TYPE)); - - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, - sizeof (NAME_TYPE)); - - ndlp->nlp_active = 1; - ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; - - /* Add the node */ - emlxs_node_add(port, ndlp); - - /* Open the node */ - emlxs_node_open(port, ndlp, hba->channel_ct); - emlxs_node_open(port, ndlp, hba->channel_els); - emlxs_node_open(port, ndlp, hba->channel_ip); - emlxs_node_open(port, ndlp, hba->channel_fcp); - } else { - wwn = (uint8_t *)&sp->portName; - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_node_create_failed_msg, - "Unable to allocate node. did=%06x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ldid, wwn[0], wwn[1], wwn[2], - wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - - return (0); - } - } else { - mutex_enter(&EMLXS_PORT_LOCK); - - ndlp->nlp_Rpi = 0xffff; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, - (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); - - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); - - wwn = (uint8_t *)&ndlp->nlp_portname; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, - "node=%p did=%06x rpi=%x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], - wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - - mutex_exit(&EMLXS_PORT_LOCK); - - /* Open the node */ - emlxs_node_open(port, ndlp, hba->channel_ct); - emlxs_node_open(port, ndlp, hba->channel_els); - emlxs_node_open(port, ndlp, hba->channel_ip); - emlxs_node_open(port, ndlp, hba->channel_fcp); - } - - bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t)); - - if (sp->VALID_VENDOR_VERSION) { - - bcopy((caddr_t *)&sp->vendorVersion[0], - (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); - - vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); - vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); - - if ((vvl.un0.w0.oui == 0x0000C9) && - (vvl.un1.w1.vport)) { - ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; - } - } - - if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - /* If link not already down then */ - /* declare it down now */ - if (emlxs_mb_read_sparam(hba, mbox) == 0) { - emlxs_mb_put(hba, mbox); - } else { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); - } - } - - /* Since this is a fabric login */ - /* - * If NPIV Fabric support has just been established on - * the physical port, then notify the vports of the - * link up - */ - EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); - if ((hba->flag & FC_NPIV_ENABLED) && - (hba->flag & FC_NPIV_SUPPORTED)) { - /* Skip the physical port */ - for (i = 1; i < MAX_VPORTS; i++) { - vport = &VPORT(i); - - if (!(vport->flag & EMLXS_PORT_BOUND) || - !(vport->flag & EMLXS_PORT_ENABLE)) { - continue; - } - - emlxs_port_online(vport); - } - } - -#ifdef SFCT_SUPPORT - if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) { - emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp; - - if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) { - mbq->sbp = NULL; - - mutex_enter(&EMLXS_PKT_LOCK); - cmd_sbp->node = ndlp; - cv_broadcast(&EMLXS_PKT_CV); - mutex_exit(&EMLXS_PKT_LOCK); - } - } -#endif /* SFCT_SUPPORT */ - return (0); - -} /* emlxs_mb_cmpl_reg_vfi */ - - /*ARGSUSED*/ -extern int -emlxs_mb_reg_vfi(emlxs_hba_t *hba, MAILBOXQ *mbq, VFIobj_t *vfip, - emlxs_port_t *port) +extern void +emlxs_mb_mcc_create_ext(emlxs_hba_t *hba, MAILBOXQ *mbq) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; - FCFIobj_t *fcfp; - MATCHMAP *mp; - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { - return (0); - } - - mb->mbxCommand = MBX_REG_VFI; - mb->mbxOwner = OWN_HOST; - mb->un.varRegVFI4.vfi = vfip->VFI; - if (!(port->flag & EMLXS_PORT_REGISTERED)) { - mb->un.varRegVFI4.vp = 1; - mb->un.varRegVFI4.vpi = port->vpi + hba->vpi_base; - } - fcfp = vfip->FCFIp; - mb->un.varRegVFI4.fcfi = fcfp->FCFI; - mb->un.varRegVFI4.sid = port->did; - - /* in ms */ - mb->un.varRegVFI4.edtov = fcfp->fcf_sparam.cmn.e_d_tov; - - /* Convert to seconds */ - mb->un.varRegVFI4.ratov = (fcfp->fcf_sparam.cmn.w2.r_a_tov + - 999) / 1000; - - mb->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM); - mb->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys); - mb->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys); - bcopy((uint32_t *)&fcfp->fcf_sparam, - (uint32_t *)mp->virt, sizeof (SERV_PARM)); + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; + IOCTL_COMMON_MCC_CREATE_EXT *qp; + uint64_t addr; - mbq->mbox_cmpl = emlxs_mb_cmpl_reg_vfi; + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); + mbq->nonembed = NULL; + mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; /* - * save address for completion + * Signifies an embedded command */ - mbq->bp = (uint8_t *)mp; - mbq->context = (uint8_t *)port; - return (1); - -} /* emlxs_mb_reg_vfi() */ - - -/*ARGSUSED*/ -extern int -emlxs_mb_unreg_vfi(emlxs_hba_t *hba, VFIobj_t *vfip) -{ - FCFIobj_t *fcfp; - MAILBOX4 *mb; - MAILBOXQ *mbq; - uint32_t rval; - - mutex_enter(&EMLXS_PORT_LOCK); - if (!(vfip->state & RESOURCE_VFI_REG)) { - mutex_exit(&EMLXS_PORT_LOCK); - return (1); - - } - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - mutex_exit(&EMLXS_PORT_LOCK); - return (1); - } + mb4->un.varSLIConfig.be.embedded = 1; - vfip->state &= ~RESOURCE_VFI_REG; - mutex_exit(&EMLXS_PORT_LOCK); - - mb = (MAILBOX4 *)mbq->mbox; - - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - - mb->mbxCommand = MBX_UNREG_VFI; - mb->mbxOwner = OWN_HOST; + mb4->mbxCommand = MBX_SLI_CONFIG; + mb4->mbxOwner = OWN_HOST; + mb4->un.varSLIConfig.be.payload_length = + sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem = + IOCTL_SUBSYSTEM_COMMON; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = + COMMON_OPCODE_MCC_CREATE_EXT; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0; + mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = + sizeof (IOCTL_COMMON_MCC_CREATE_EXT); - mb->un.varUnRegVFI4.vfi = vfip->VFI; + addr = hba->sli.sli4.mq.addr.phys; + qp = (IOCTL_COMMON_MCC_CREATE_EXT *)&mb4->un.varSLIConfig.payload; - mbq->mbox_cmpl = NULL; + qp->params.request.num_pages = 1; + qp->params.request.async_event_bitmap = + ASYNC_LINK_EVENT | ASYNC_FCF_EVENT | ASYNC_GROUP5_EVENT; + qp->params.request.context.Size = MQ_ELEMENT_COUNT_16; + qp->params.request.context.Valid = 1; + qp->params.request.context.CQId = hba->sli.sli4.mq.cqid; - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } + qp->params.request.pages[0].addrLow = PADDR_LO(addr); + qp->params.request.pages[0].addrHigh = PADDR_HI(addr); - fcfp = vfip->FCFIp; - if (vfip == fcfp->fcf_vfi) { - fcfp->fcf_vfi = NULL; - } - emlxs_sli4_free_vfi(hba, vfip); - return (1); + return; -} /* emlxs_mb_unreg_vfi() */ +} /* emlxs_mb_mcc_create_ext() */ /*ARGSUSED*/ @@ -1264,6 +538,7 @@ emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxOwner = OWN_HOST; mb->un.varWords[0] = hba->channel_els; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -1281,6 +556,7 @@ emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_HEARTBEAT; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed for hbeat */ + mbq->port = (void *)&PPORT; return; @@ -1295,7 +571,7 @@ emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, uint32_t intr_count) { MAILBOX *mb = (MAILBOX *)mbq; - uint32_t i; + uint16_t i; uint32_t mask; bzero((void *)mb, MAILBOX_CMD_BSIZE); @@ -1363,6 +639,7 @@ emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -1375,7 +652,7 @@ emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, uint32_t intr_count) { MAILBOX *mb = (MAILBOX *)mbq; - uint32_t i; + uint8_t i; uint32_t mask; bzero((void *)mb, MAILBOX_CMD_BSIZE); @@ -1443,6 +720,7 @@ emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map, mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -1464,6 +742,7 @@ emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t ringno) mb->un.varRstRing.ring_no = ringno; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -1476,27 +755,27 @@ emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset) { if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; /* Clear the local dump_region */ bzero(hba->sli.sli4.dump_region.virt, hba->sli.sli4.dump_region.size); - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); - mb->mbxCommand = MBX_DUMP_MEMORY; - mb->un.varDmp4.type = DMP_NV_PARAMS; - mb->un.varDmp4.entry_index = offset; - mb->un.varDmp4.region_id = DMP_VPD_REGION; + mb4->mbxCommand = MBX_DUMP_MEMORY; + mb4->un.varDmp4.type = DMP_NV_PARAMS; + mb4->un.varDmp4.entry_index = offset; + mb4->un.varDmp4.region_id = DMP_VPD_REGION; - mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; - mb->un.varDmp4.addrHigh = + mb4->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; + mb4->un.varDmp4.addrHigh = PADDR_HI(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.addrLow = + mb4->un.varDmp4.addrLow = PADDR_LO(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.rsp_cnt = 0; + mb4->un.varDmp4.rsp_cnt = 0; - mb->mbxOwner = OWN_HOST; + mb4->mbxOwner = OWN_HOST; } else { MAILBOX *mb = (MAILBOX *)mbq; @@ -1518,40 +797,44 @@ emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset) } mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_mb_dump_vpd() */ +/* SLI4 */ /*ARGSUSED*/ extern void emlxs_mb_dump_fcoe(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; - if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) { return; } + /* Clear the local dump_region */ bzero(hba->sli.sli4.dump_region.virt, hba->sli.sli4.dump_region.size); - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); - mb->mbxCommand = MBX_DUMP_MEMORY; - mb->un.varDmp4.type = DMP_NV_PARAMS; - mb->un.varDmp4.entry_index = offset; - mb->un.varDmp4.region_id = DMP_FCOE_REGION; + mb4->mbxCommand = MBX_DUMP_MEMORY; + mb4->un.varDmp4.type = DMP_NV_PARAMS; + mb4->un.varDmp4.entry_index = offset; + mb4->un.varDmp4.region_id = DMP_FCOE_REGION; - mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; - mb->un.varDmp4.addrHigh = + mb4->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size; + mb4->un.varDmp4.addrHigh = PADDR_HI(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.addrLow = + mb4->un.varDmp4.addrLow = PADDR_LO(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.rsp_cnt = 0; + mb4->un.varDmp4.rsp_cnt = 0; - mb->mbxOwner = OWN_HOST; + mb4->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_mb_dump_fcoe() */ @@ -1562,28 +845,28 @@ emlxs_mb_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset, uint32_t words) { if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - MAILBOX4 *mb = (MAILBOX4 *)mbq; + MAILBOX4 *mb4 = (MAILBOX4 *)mbq; /* Clear the local dump_region */ bzero(hba->sli.sli4.dump_region.virt, hba->sli.sli4.dump_region.size); - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); + bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE); - mb->mbxCommand = MBX_DUMP_MEMORY; - mb->un.varDmp4.type = DMP_MEM_REG; - mb->un.varDmp4.entry_index = offset; - mb->un.varDmp4.region_id = 0; + mb4->mbxCommand = MBX_DUMP_MEMORY; + mb4->un.varDmp4.type = DMP_MEM_REG; + mb4->un.varDmp4.entry_index = offset; + mb4->un.varDmp4.region_id = 0; - mb->un.varDmp4.available_cnt = min((words*4), + mb4->un.varDmp4.available_cnt = min((words*4), hba->sli.sli4.dump_region.size); - mb->un.varDmp4.addrHigh = + mb4->un.varDmp4.addrHigh = PADDR_HI(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.addrLow = + mb4->un.varDmp4.addrLow = PADDR_LO(hba->sli.sli4.dump_region.phys); - mb->un.varDmp4.rsp_cnt = 0; + mb4->un.varDmp4.rsp_cnt = 0; - mb->mbxOwner = OWN_HOST; + mb4->mbxOwner = OWN_HOST; } else { @@ -1602,6 +885,7 @@ emlxs_mb_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset, uint32_t words) } mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -1622,6 +906,7 @@ emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_READ_NV; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_mb_read_nv() */ @@ -1651,6 +936,7 @@ emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t v3) mb->mbxCommand = MBX_READ_REV; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; + mbq->port = (void *)&PPORT; } /* emlxs_mb_read_rev() */ @@ -1676,6 +962,7 @@ emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOXQ *mbq, uint64_t out, mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = PADDR_LO(in); mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return (0); } /* emlxs_mb_run_biu_diag() */ @@ -1708,25 +995,25 @@ emlxs_mb_retry(emlxs_hba_t *hba, MAILBOXQ *mbq) HBASTATS.MboxGood++; } - hba->mbox_mbq = 0; + hba->mbox_mbq = NULL; hba->mbox_queue_flag = 0; mutex_exit(&EMLXS_PORT_LOCK); rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } return; } /* emlxs_mb_retry() */ -int -emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) +/* SLI3 */ +static uint32_t +emlxs_read_la_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; MAILBOXQ *mbox; MATCHMAP *mp; @@ -1761,8 +1048,7 @@ emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) mutex_exit(&EMLXS_PORT_LOCK); return (0); } - bcopy((uint32_t *)((char *)mb + sizeof (uint32_t)), - (uint32_t *)&la, sizeof (READ_LA_VAR)); + bcopy((void *)&mb->un.varReadLA, (void *)&la, sizeof (READ_LA_VAR)); mp = (MATCHMAP *)mbq->bp; if (mp) { @@ -1900,7 +1186,7 @@ emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) if (la.fa == 1) { emlxs_thread_spawn(hba, emlxs_fcoe_attention_thread, - NULL, NULL); + 0, 0); } } #endif /* MENLO_SUPPORT */ @@ -1921,8 +1207,8 @@ emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) if (emlxs_mb_read_sparam(hba, mbox) == 0) { emlxs_mb_put(hba, mbox); } else { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox); } } @@ -1957,16 +1243,12 @@ emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq) mutex_exit(&EMLXS_PORT_LOCK); - /* Log the link event */ - emlxs_log_link_event(port); return (0); -} /* emlxs_cmpl_read_la() */ +} /* emlxs_read_la_mbcmpl() */ -/* - * emlxs_mb_read_la Issue a READ LA mailbox command - */ +/* SLI3 */ extern uint32_t emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOXQ *mbq) { @@ -1986,23 +1268,24 @@ emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys); mb->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys); mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_read_la; + mbq->mbox_cmpl = emlxs_read_la_mbcmpl; + mbq->port = (void *)&PPORT; /* * save address for completion */ - ((MAILBOXQ *)mb)->bp = (uint8_t *)mp; + mbq->bp = (void *)mp; return (0); } /* emlxs_mb_read_la() */ -int -emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq) +/* SLI3 */ +static uint32_t +emlxs_clear_la_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; MAILBOXQ *mbox; emlxs_port_t *vport; @@ -2024,13 +1307,13 @@ emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq) (MAILBOX *)mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, - MEM_MBOX, (uint8_t *)mbox); + emlxs_mem_put(hba, + MEM_MBOX, (void *)mbox); } la_enable = 0; } else { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox); } } } @@ -2085,6 +1368,7 @@ emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq) /* Adapter is now ready for FCP traffic */ if (hba->state == FC_READY) { + /* Register vpi's for all ports that have did's */ for (i = 0; i < MAX_VPORTS; i++) { vport = &VPORT(i); @@ -2102,12 +1386,10 @@ emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq) } return (0); -} /* emlxs_cmpl_clear_la() */ +} /* emlxs_clear_la_mbcmpl() */ -/* - * emlxs_mb_clear_la Issue a CLEAR LA mailbox command - */ +/* SLI3 */ extern void emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOXQ *mbq) { @@ -2122,7 +1404,8 @@ emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->un.varClearLA.eventTag = hba->link_event_tag; mb->mbxCommand = MBX_CLEAR_LA; mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_clear_la; + mbq->mbox_cmpl = emlxs_clear_la_mbcmpl; + mbq->port = (void *)&PPORT; return; @@ -2143,6 +1426,7 @@ emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_READ_STATUS; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* fc_read_status() */ @@ -2161,62 +1445,13 @@ emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_READ_LNK_STAT; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_mb_read_lnk_stat() */ -/* - * emlxs_mb_write_nv Issue a WRITE NVPARAM mailbox command - */ -static void -emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq) -{ - MAILBOX *mb = (MAILBOX *)mbq; - int32_t i; - emlxs_config_t *cfg = &CFG; - - bzero((void *)mb, MAILBOX_CMD_BSIZE); - - bcopy((void *)&hba->wwnn, - (void *)mb->un.varWTnvp.nodename, sizeof (NAME_TYPE)); - - bcopy((void *)&hba->wwpn, - (void *)mb->un.varWTnvp.portname, sizeof (NAME_TYPE)); - - mb->un.varWTnvp.pref_DID = 0; - mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current; - mb->un.varWTnvp.rsvd1[0] = 0xffffffff; - mb->un.varWTnvp.rsvd1[1] = 0xffffffff; - mb->un.varWTnvp.rsvd1[2] = 0xffffffff; - for (i = 0; i < 21; i++) { - mb->un.varWTnvp.rsvd3[i] = 0xffffffff; - } - - mb->mbxCommand = MBX_WRITE_NV; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - -} /* emlxs_mb_write_nv() */ - - -/* - * emlxs_mb_part_slim Issue a PARTITION SLIM mailbox command - */ -static void -emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t hbainit) -{ - MAILBOX *mb = (MAILBOX *)mbq; - - bzero((void *)mb, MAILBOX_CMD_BSIZE); - mb->un.varSlim.numRing = hba->chan_count; - mb->un.varSlim.hbainit = hbainit; - mb->mbxCommand = MBX_PART_SLIM; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - -} /* emlxs_mb_part_slim() */ /* @@ -2260,6 +1495,7 @@ emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOXQ *mbq) mb->mbxCommand = MBX_CONFIG_RING; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return; @@ -2302,17 +1538,17 @@ emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_CONFIG_LINK; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; + mbq->port = (void *)port; return; } /* emlxs_mb_config_link() */ -int -emlxs_cmpl_init_link(void *arg1, MAILBOXQ *mbq) +static uint32_t +emlxs_init_link_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; emlxs_config_t *cfg = &CFG; MAILBOX *mb; @@ -2343,7 +1579,7 @@ emlxs_cmpl_init_link(void *arg1, MAILBOXQ *mbq) } return (0); -} /* emlxs_cmpl_init_link() */ +} /* emlxs_init_link_mbcmpl() */ /* @@ -2361,6 +1597,7 @@ emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t topology, bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); mbq->nonembed = NULL; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK; mb->mbxOwner = OWN_HOST; @@ -2449,7 +1686,8 @@ emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t topology, (uint8_t)cfg[CFG_ASSIGN_ALPA].current; mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK; mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_init_link; + mbq->mbox_cmpl = emlxs_init_link_mbcmpl; + mbq->port = (void *)&PPORT; return; @@ -2471,17 +1709,17 @@ emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_DOWN_LINK; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; + mbq->port = (void *)&PPORT; return; } /* emlxs_mb_down_link() */ -int -emlxs_cmpl_read_sparam(void *arg1, MAILBOXQ *mbq) +static uint32_t +emlxs_read_sparam_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; MATCHMAP *mp; emlxs_port_t *vport; @@ -2526,7 +1764,7 @@ emlxs_cmpl_read_sparam(void *arg1, MAILBOXQ *mbq) } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "SPARAM: EDTOV hba=x%x mbox_csp=x%x, BBC=x%x", + "SPARAM: EDTOV hba=%x mbox_csp=%x BBC=%x", hba->fc_edtov, hba->sparam.cmn.e_d_tov, hba->sparam.cmn.bbCreditlsb); @@ -2562,7 +1800,7 @@ emlxs_cmpl_read_sparam(void *arg1, MAILBOXQ *mbq) return (0); -} /* emlxs_cmpl_read_sparam() */ +} /* emlxs_read_sparam_mbcmpl() */ /* @@ -2587,12 +1825,13 @@ emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys); mb->mbxCommand = MBX_READ_SPARM64; mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_read_sparam; + mbq->mbox_cmpl = emlxs_read_sparam_mbcmpl; + mbq->port = (void *)&PPORT; /* * save address for completion */ - mbq->bp = (uint8_t *)mp; + mbq->bp = (void *)mp; return (0); @@ -2619,6 +1858,7 @@ emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOXQ *mbq, mb->mbxCommand = MBX_READ_RPI64; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return (0); } /* emlxs_mb_read_rpi() */ @@ -2644,6 +1884,7 @@ emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOXQ *mbq, mb->mbxCommand = MBX_READ_XRI; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; return (0); } /* emlxs_mb_read_xri() */ @@ -2704,26 +1945,25 @@ emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp) } /* emlxs_mb_check_sparm() */ -int -emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) +/* SLI3 */ +static uint32_t +emlxs_reg_did_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; MATCHMAP *mp; NODELIST *ndlp; emlxs_port_t *vport; - uint8_t *wwn; - volatile SERV_PARM *sp; + SERV_PARM *sp; int32_t i; uint32_t control; uint32_t ldata; uint32_t ldid; uint16_t lrpi; uint16_t lvpi; - emlxs_vvl_fmt_t vvl; mb = (MAILBOX *)mbq; + if (mb->mbxStatus) { if (mb->mbxStatus == MBXERR_NO_RESOURCES) { control = mb->un.varRegLogin.un.sp.bdeSize; @@ -2738,8 +1978,6 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) return (1); } if (mb->mbxStatus == MBXERR_RPI_FULL) { - port = &VPORT((mb->un.varRegLogin.vpi - hba->vpi_base)); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, "Limit reached. count=%d", port->node_count); @@ -2757,6 +1995,7 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) if (!mp) { return (0); } + ldata = mb->un.varWords[5]; lvpi = (ldata & 0xffff) - hba->vpi_base; port = &VPORT(lvpi); @@ -2768,105 +2007,17 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) ldata = mb->un.varWords[1]; /* get did */ ldid = ldata & MASK_DID; - sp = (volatile SERV_PARM *)mp->virt; - ndlp = emlxs_node_find_did(port, ldid); - - if (!ndlp) { - /* Attempt to create a node */ - if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { - ndlp->nlp_Rpi = lrpi; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, - sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, - sizeof (NAME_TYPE)); - - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, - sizeof (NAME_TYPE)); - - ndlp->nlp_active = 1; - ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; + sp = (SERV_PARM *)mp->virt; - /* Add the node */ - emlxs_node_add(port, ndlp); + /* Create or update the node */ + ndlp = emlxs_node_create(port, ldid, lrpi, sp); - /* Open the node */ - emlxs_node_open(port, ndlp, hba->channel_ct); - emlxs_node_open(port, ndlp, hba->channel_els); - emlxs_node_open(port, ndlp, hba->channel_ip); - emlxs_node_open(port, ndlp, hba->channel_fcp); - } else { - wwn = (uint8_t *)&sp->portName; - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_node_create_failed_msg, - "Unable to allocate node. did=%06x rpi=%x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ldid, lrpi, wwn[0], wwn[1], wwn[2], - wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - - return (0); - } - } else { + if (ndlp->nlp_DID == FABRIC_DID) { + /* FLOGI/FDISC successfully completed on this port */ mutex_enter(&EMLXS_PORT_LOCK); - - ndlp->nlp_Rpi = lrpi; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, - (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); - - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); - - wwn = (uint8_t *)&ndlp->nlp_portname; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, - "node=%p did=%06x rpi=%x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], - wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - + port->flag |= EMLXS_PORT_FLOGI_CMPL; mutex_exit(&EMLXS_PORT_LOCK); - /* Open the node */ - emlxs_node_open(port, ndlp, hba->channel_ct); - emlxs_node_open(port, ndlp, hba->channel_els); - emlxs_node_open(port, ndlp, hba->channel_ip); - emlxs_node_open(port, ndlp, hba->channel_fcp); - } - - bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t)); - - if (sp->VALID_VENDOR_VERSION) { - - bcopy((caddr_t *)&sp->vendorVersion[0], - (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); - - vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); - vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); - - if ((vvl.un0.w0.oui == 0x0000C9) && - (vvl.un1.w1.vport)) { - ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; - } - } - - if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && - (ndlp->nlp_DID == NAMESERVER_DID)) { - EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY); - } - - /* If this was a fabric login */ - if (ndlp->nlp_DID == FABRIC_DID) { /* If CLEAR_LA has been sent, then attempt to */ /* register the vpi now */ if (hba->state == FC_READY) { @@ -2886,7 +2037,8 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) vport = &VPORT(i); if (!(vport->flag & EMLXS_PORT_BOUND) || - !(vport->flag & EMLXS_PORT_ENABLE)) { + !(vport->flag & + EMLXS_PORT_ENABLE)) { continue; } @@ -2895,9 +2047,16 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) } } + /* Check for special restricted login flag */ if (mbq->iocbq == (uint8_t *)1) { mbq->iocbq = NULL; - (void) emlxs_mb_unreg_did(port, ldid, NULL, NULL, NULL); + (void) emlxs_mb_unreg_node(port, ndlp, NULL, NULL, NULL); + return (0); + } + + /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */ + if (mbq->sbp) { + ((emlxs_buf_t *)mbq->sbp)->node = ndlp; } #ifdef DHCHAP_SUPPORT @@ -2912,28 +2071,12 @@ emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq) } #endif /* DHCHAP_SUPPORT */ -#ifdef SFCT_SUPPORT - if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) { - emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp; - - if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) { - mbq->sbp = NULL; - - mutex_enter(&EMLXS_PKT_LOCK); - cmd_sbp->node = ndlp; - cv_broadcast(&EMLXS_PKT_CV); - mutex_exit(&EMLXS_PKT_LOCK); - } - } -#endif /* SFCT_SUPPORT */ return (0); -} /* emlxs_cmpl_reg_did() */ +} /* emlxs_reg_did_mbcmpl() */ -/* - * emlxs_mb_reg_did Issue a REG_LOGIN mailbox command - */ +/* SLI3 */ extern uint32_t emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) @@ -2942,10 +2085,13 @@ emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, MATCHMAP *mp; MAILBOXQ *mbq; MAILBOX *mb; - NODELIST *node; - RPIobj_t *rp = NULL; uint32_t rval; + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + rval = emlxs_sli4_reg_did(port, did, param, sbp, ubp, iocbq); + return (rval); + } + /* Check for invalid node ids to register */ if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { return (1); @@ -2979,38 +2125,16 @@ emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, return (1); } mb = (MAILBOX *)mbq->mbox; + bzero((void *)mb, MAILBOX_CMD_BSIZE); /* Build login request */ if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) { + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, "Unable to allocate buffer. did=%x", did); - - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); return (1); } - - /* - * If we are SLI4, the RPI number gets assigned by the driver. - * For SLI3, the firmware assigns the RPI number. - */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - node = emlxs_node_find_did(port, did); - rp = EMLXS_NODE_TO_RPI(hba, node); - - if (!rp) { - rp = emlxs_sli4_alloc_rpi(port); - } - - if (!rp) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, - "Unable to get an rpi. did=%x", did); - - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - return (1); - } - rp->state &= ~RESOURCE_RPI_PAUSED; - } - bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM)); mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); @@ -3020,258 +2144,151 @@ emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, mb->un.varWords[30] = 0; /* flags */ mb->mbxCommand = MBX_REG_LOGIN64; mb->mbxOwner = OWN_HOST; - mb->un.varRegLogin.vpi = port->vpi + hba->vpi_base; - mb->un.varRegLogin.rpi = (rp)? rp->RPI: 0; + mb->un.varRegLogin.vpi = port->vpi; + mb->un.varRegLogin.rpi = 0; - mbq->sbp = (uint8_t *)sbp; - mbq->ubp = (uint8_t *)ubp; - mbq->iocbq = (uint8_t *)iocbq; - mbq->bp = (uint8_t *)mp; - mbq->mbox_cmpl = emlxs_cmpl_reg_did; + mbq->sbp = (void *)sbp; + mbq->ubp = (void *)ubp; + mbq->iocbq = (void *)iocbq; + mbq->bp = (void *)mp; + mbq->mbox_cmpl = emlxs_reg_did_mbcmpl; + mbq->context = NULL; + mbq->port = (void *)port; rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - if (rp) { - emlxs_sli4_free_rpi(hba, rp); - } + emlxs_mem_put(hba, MEM_BUF, (void *)mp); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, + "Unable to send mbox. did=%x", did); + return (1); } return (0); } /* emlxs_mb_reg_did() */ -/* - * emlxs_mb_unreg_rpi Issue a UNREG_LOGIN mailbox command - */ -extern uint32_t -emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp, - fc_unsol_buf_t *ubp, IOCBQ *iocbq) +/* SLI3 */ +/*ARGSUSED*/ +static uint32_t +emlxs_unreg_node_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = HBA; - MAILBOXQ *mbq; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; - NODELIST *ndlp; - int rval; - - if (rpi != 0xffff) { - /* Make sure the node does already exist */ - ndlp = emlxs_node_find_rpi(port, rpi); - - - if (ndlp) { - /* - * If we just unregistered the host node then - * clear the host DID - */ - if (ndlp->nlp_DID == port->did) { - port->did = 0; - } - - /* remove it */ - emlxs_node_rm(port, ndlp); - - } else { - return (1); - } - } else { /* Unreg all */ - - emlxs_node_destroy_all(port); - } - - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - return (1); - } + NODELIST *node; + uint16_t rpi; - mb = (MAILBOX *)mbq->mbox; + node = (NODELIST *)mbq->context; + mb = (MAILBOX *)mbq; + rpi = (node)? node->nlp_Rpi:0xffff; -#define INDEX_INDICATOR_VPI 1 + if (mb->mbxStatus) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node_mbcmpl:failed. node=%p rpi=%x status=%x", + node, rpi, mb->mbxStatus); - if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && (rpi == 0xffff)) { - mb->un.varUnregLogin.ll = INDEX_INDICATOR_VPI; - mb->un.varUnregLogin.rpi = (uint16_t)port->vpi + hba->vpi_base; - } else { - mb->un.varUnregLogin.rpi = (uint16_t)rpi; + return (0); } - mb->un.varUnregLogin.vpi = port->vpi + hba->vpi_base; - mb->mbxCommand = MBX_UNREG_LOGIN; - mb->mbxOwner = OWN_HOST; - mbq->sbp = (uint8_t *)sbp; - mbq->ubp = (uint8_t *)ubp; - mbq->iocbq = (uint8_t *)iocbq; - mbq->mbox_cmpl = NULL; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node_mbcmpl: node=%p rpi=%x", + node, rpi); - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } + if (node) { + emlxs_node_rm(port, node); - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - port->outstandingRPIs--; - if ((port->outstandingRPIs == 0) && - (hba->state == FC_LINK_DOWN)) { - /* No more RPIs so unreg the VPI */ - (void) emlxs_mb_unreg_vpi(port); - } + } else { /* All nodes */ + emlxs_node_destroy_all(port); } return (0); -} /* emlxs_mb_unreg_rpi() */ +} /* emlxs_unreg_node_mbcmpl */ -/* - * emlxs_mb_unreg_did Issue a UNREG_DID mailbox command - */ + +/* SLI3 */ extern uint32_t -emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp, +emlxs_mb_unreg_node(emlxs_port_t *port, NODELIST *node, emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) { emlxs_hba_t *hba = HBA; - NODELIST *ndlp; MAILBOXQ *mbq; MAILBOX *mb; - int rval = 0; + uint16_t rpi; + uint32_t rval; - /* - * Unregister all default RPIs if did == 0xffffffff - */ - if (did != 0xffffffff) { + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + rval = emlxs_sli4_unreg_node(port, node, sbp, ubp, iocbq); + return (rval); + } + + if (node) { /* Check for base node */ - if (did == BCAST_DID) { + if (node == &port->node_base) { /* just flush base node */ (void) emlxs_tx_node_flush(port, &port->node_base, 0, 0, 0); (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); + port->did = 0; + /* Return now */ return (1); } + rpi = (uint16_t)node->nlp_Rpi; - /* - * A zero DID means that we are trying to unreg the host node - * after a link bounce - */ - - /* - * If the prev_did == 0 then the adapter has been reset and - * there is no need in unregistering - */ - - /* - * If the prev_did != 0 then we can look for the hosts - * last known DID node - */ - - if (did == 0) { - if (port->prev_did == 0) { - return (1); - } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node:%p rpi=%d", node, rpi); - did = port->prev_did; + /* This node must be (0xFFFFFE) which registered by vport */ + if (rpi == 0) { + emlxs_node_rm(port, node); + return (0); } - /* Make sure the node does already exist */ - ndlp = emlxs_node_find_did(port, did); - - if (ndlp) { - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - /* Use UNREG_RPI for SLI4 */ - if (ndlp->nlp_Rpi != 0xffff) { - rval = emlxs_mb_unreg_rpi(port, - ndlp->nlp_Rpi, sbp, ubp, iocbq); - } - return (rval); - } - /* remove it */ - emlxs_node_rm(port, ndlp); - - /* - * If we just unregistered the host node then - * clear the host DID - */ - if (did == port->did) { - port->did = 0; - } + } else { /* Unreg all nodes */ + rpi = 0xffff; - } else { - return (1); - } - } else { - /* SLI4 doesn't have dflt RPIs in SLI Port */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - return (0); - } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node: All"); } if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node:failed. Unable to allocate mbox"); return (1); } mb = (MAILBOX *)mbq->mbox; - mb->un.varUnregDID.did = did; - mb->un.varUnregDID.vpi = port->vpi + hba->vpi_base; - mb->mbxCommand = MBX_UNREG_D_ID; + mb->un.varUnregLogin.rpi = rpi; + mb->un.varUnregLogin.vpi = port->VPIobj.VPI; + + mb->mbxCommand = MBX_UNREG_LOGIN; mb->mbxOwner = OWN_HOST; - mbq->sbp = (uint8_t *)sbp; - mbq->ubp = (uint8_t *)ubp; - mbq->iocbq = (uint8_t *)iocbq; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->sbp = (void *)sbp; + mbq->ubp = (void *)ubp; + mbq->iocbq = (void *)iocbq; + mbq->mbox_cmpl = emlxs_unreg_node_mbcmpl; + mbq->context = (void *)node; + mbq->port = (void *)port; rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node:failed. Unable to send request."); + + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + return (1); } return (0); -} /* emlxs_mb_unreg_did() */ - - -/* - * emlxs_mb_set_mask Issue a SET MASK mailbox command - */ -/*ARGSUSED*/ -static void -emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t mask, - uint32_t ringno) -{ - MAILBOX *mb = (MAILBOX *)mbq; - - bzero((void *)mb, MAILBOX_CMD_BSIZE); - - mb->un.varWords[0] = 0x11223344; /* set passwd */ - mb->un.varWords[1] = mask; /* set mask */ - mb->un.varWords[2] = ringno; /* set ringno */ - mb->mbxCommand = MBX_SET_MASK; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - -} /* emlxs_mb_set_mask() */ - - -/* - * emlxs_mb_set_debug Issue a special debug mailbox command - */ -/*ARGSUSED*/ -static void -emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t word0, - uint32_t word1, uint32_t word2) -{ - MAILBOX *mb = (MAILBOX *)mbq; - - bzero((void *)mb, MAILBOX_CMD_BSIZE); +} /* emlxs_mb_unreg_node() */ - mb->un.varWords[0] = word0; - mb->un.varWords[1] = word1; - mb->un.varWords[2] = word2; - mb->mbxCommand = MBX_SET_DEBUG; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ -} /* emlxs_mb_set_debug() */ /* @@ -3302,6 +2319,7 @@ emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t addr, mb->mbxCommand = MBX_SET_VARIABLE; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_mb_set_var() */ @@ -3323,6 +2341,7 @@ emlxs_disable_tc(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_SET_VARIABLE; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; } /* emlxs_disable_tc() */ @@ -3351,6 +2370,7 @@ emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOXQ *mbq, int hbq_id) mb->mbxCommand = MBX_CONFIG_HBQ; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; + mbq->port = (void *)&PPORT; /* Copy info for profiles 2,3,5. Other profiles this area is reserved */ if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) || @@ -3380,196 +2400,65 @@ emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOXQ *mbq, int hbq_id) } /* emlxs_mb_config_hbq() */ -int -emlxs_cmpl_init_vpi(void *arg1, MAILBOXQ *mbq) -{ - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - emlxs_port_t *vport; - MAILBOX4 *mb; - - mb = (MAILBOX4 *)mbq; - - if (mb->mbxStatus == MBX_SUCCESS) { - vport = &VPORT((mb->un.varInitVPI4.vpi - hba->vpi_base)); - vport->flag |= EMLXS_PORT_INIT_VPI_CMPL; - } - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL init_vpi: stats: %x", mb->mbxStatus); - - return (0); - -} /* emlxs_cmpl_init_vpi() */ - - -extern uint32_t -emlxs_mb_init_vpi(emlxs_port_t *port) -{ - emlxs_hba_t *hba = HBA; - emlxs_port_t *phy_port = &PPORT; - MAILBOXQ *mbq; - MAILBOX4 *mb; - int rval; - - if (!(hba->flag & FC_NPIV_ENABLED)) { - return (0); - } - - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - return (1); - } - - - mb = (MAILBOX4 *)mbq->mbox; - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - mbq->nonembed = NULL; - mb->un.varInitVPI4.vfi = phy_port->VFIp->VFI; - mb->un.varInitVPI4.vpi = port->vpi + hba->vpi_base; - mb->mbxCommand = MBX_INIT_VPI; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_init_vpi; - - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } - - return (0); - -} /* emlxs_mb_init_vpi() */ - -/* Leadville wll start sending PLOGI right after */ -/* FDISC completion, we need to wait for REG_VPI */ -/* completion, before sending back the FDISK request */ -/* Also, allocate a node structure for Fabric port */ -int -emlxs_cmpl_reg_vpi(void *arg1, MAILBOXQ *mbq) +/* SLI3 */ +static uint32_t +emlxs_reg_vpi_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *port = &PPORT; - emlxs_port_t *vport; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; MAILBOX *mb; - emlxs_buf_t *sbp; - SERV_PARM *sp; - fc_packet_t *pkt; - NODELIST *ndlp; - uint32_t ldid; - uint8_t *wwn; mb = (MAILBOX *)mbq; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CMPL reg_vpi: stats: %x", mb->mbxStatus); + mutex_enter(&EMLXS_PORT_LOCK); if (mb->mbxStatus != MBX_SUCCESS) { - return (0); - } - - vport = &VPORT((mb->un.varRegVpi.vpi - hba->vpi_base)); - vport->flag |= EMLXS_PORT_REG_VPI_CMPL; - sbp = (emlxs_buf_t *)mbq->sbp; + port->flag &= ~EMLXS_PORT_REG_VPI; + mutex_exit(&EMLXS_PORT_LOCK); - if (!sbp) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "cmpl_reg_vpi:%d failed. status=%x", + port->vpi, mb->mbxStatus); return (0); } - pkt = PRIV2PKT(sbp); - sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t)); - - vport->VFIp->outstandingVPIs++; - - ldid = FABRIC_DID; - ndlp = emlxs_node_find_did(vport, ldid); - - if (!ndlp) { - /* Attempt to create a node */ - if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) { - ndlp->nlp_Rpi = 0xffff; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, - sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, - sizeof (NAME_TYPE)); - - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, - sizeof (NAME_TYPE)); - - ndlp->nlp_active = 1; - ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; - ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; - - /* Add the node */ - emlxs_node_add(vport, ndlp); - - /* Open the node */ - emlxs_node_open(vport, ndlp, hba->channel_ct); - emlxs_node_open(vport, ndlp, hba->channel_els); - emlxs_node_open(vport, ndlp, hba->channel_ip); - emlxs_node_open(vport, ndlp, hba->channel_fcp); - } else { - wwn = (uint8_t *)&sp->portName; - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_node_create_failed_msg, - "Unable to allocate node. did=%06x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ldid, wwn[0], wwn[1], wwn[2], - wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - - return (0); - } - } else { - mutex_enter(&EMLXS_PORT_LOCK); - - ndlp->nlp_Rpi = 0xffff; - ndlp->nlp_DID = ldid; - - bcopy((uint8_t *)sp, - (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM)); - - bcopy((uint8_t *)&sp->nodeName, - (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE)); + port->flag |= EMLXS_PORT_REG_VPI_CMPL; - bcopy((uint8_t *)&sp->portName, - (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE)); - - wwn = (uint8_t *)&ndlp->nlp_portname; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, - "node=%p did=%06x rpi=%x " - "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", - ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], - wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); - - mutex_exit(&EMLXS_PORT_LOCK); + mutex_exit(&EMLXS_PORT_LOCK); - /* Open the node */ - emlxs_node_open(vport, ndlp, hba->channel_ct); - emlxs_node_open(vport, ndlp, hba->channel_els); - emlxs_node_open(vport, ndlp, hba->channel_ip); - emlxs_node_open(vport, ndlp, hba->channel_fcp); - } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "cmpl_reg_vpi:%d ", + port->vpi); return (0); -} /* emlxs_cmpl_reg_vpi */ +} /* emlxs_reg_vpi_mbcmpl */ + +/* SLI3 */ extern uint32_t emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) { emlxs_hba_t *hba = HBA; MAILBOXQ *mbq; MAILBOX *mb; - uint32_t *pn; int rval; + if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) { + return (1); + } + if (!(hba->flag & FC_NPIV_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. NPIV disabled.", + port->vpi); + return (1); + } + + if (port->flag & EMLXS_PORT_REG_VPI) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. Already registered.", + port->vpi); return (0); } @@ -3579,6 +2468,9 @@ emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) if (hba->state != FC_READY) { mutex_exit(&EMLXS_PORT_LOCK); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. HBA state not READY", + port->vpi); return (1); } @@ -3586,49 +2478,49 @@ emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) if (!port->did) { mutex_exit(&EMLXS_PORT_LOCK); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. Port did=0", + port->vpi); return (1); } if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { mutex_exit(&EMLXS_PORT_LOCK); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. Unable to allocate mbox.", + port->vpi); return (1); } - port->flag |= EMLXS_PORT_REGISTERED; + port->flag |= EMLXS_PORT_REG_VPI; mutex_exit(&EMLXS_PORT_LOCK); mb = (MAILBOX *)mbq->mbox; + bzero((void *)mb, MAILBOX_CMD_BSIZE); - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); - mbq->nonembed = NULL; - mb->un.varRegVpi.vfi = port->VFIp->VFI; - - pn = (uint32_t *)&port->wwpn; - mb->un.varRegVpi.portname[0] = BE_SWAP32(*pn); - pn++; - mb->un.varRegVpi.portname[1] = BE_SWAP32(*pn); - - mbq->mbox_cmpl = emlxs_cmpl_reg_vpi; - } else { - bzero((void *)mb, MAILBOX_CMD_BSIZE); - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - } - - if (sbp) { - mbq->sbp = (uint8_t *)sbp; - } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d", port->vpi); - mb->un.varRegVpi.vpi = port->vpi + hba->vpi_base; + mb->un.varRegVpi.vpi = port->vpi; mb->un.varRegVpi.sid = port->did; mb->mbxCommand = MBX_REG_VPI; mb->mbxOwner = OWN_HOST; + mbq->sbp = (void *)sbp; + mbq->mbox_cmpl = emlxs_reg_vpi_mbcmpl; + mbq->context = NULL; + mbq->port = (void *)port; + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "reg_vpi:%d failed. Unable to send request.", + port->vpi); + + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + return (1); } return (0); @@ -3636,98 +2528,96 @@ emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) } /* emlxs_mb_reg_vpi() */ -int -emlxs_cmpl_unreg_vpi(void *arg1, MAILBOXQ *mbq) +/* SLI3 */ +static uint32_t +emlxs_unreg_vpi_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) { - emlxs_hba_t *hba = (emlxs_hba_t *)arg1; - emlxs_port_t *vport; - MAILBOX4 *mb4; - uint16_t vpi; + emlxs_port_t *port = (emlxs_port_t *)mbq->port; + MAILBOX *mb; - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - mb4 = (MAILBOX4 *)mbq->mbox; - if (mb4->mbxStatus == MBX_SUCCESS) { - vpi = mb4->un.varUnRegVPI4.index - hba->vpi_base; - vport = &VPORT(vpi); - vport->flag &= ~EMLXS_PORT_INIT_VPI_CMPL; - vport->flag &= ~EMLXS_PORT_REG_VPI_CMPL; - } + mb = (MAILBOX *)mbq->mbox; + + if (mb->mbxStatus != MBX_SUCCESS) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi_mbcmpl:%d failed. status=%x", + port->vpi, mb->mbxStatus); + return (0); } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi_mbcmpl:%d", port->vpi); + + mutex_enter(&EMLXS_PORT_LOCK); + port->flag &= ~EMLXS_PORT_REG_VPI_CMPL; + mutex_exit(&EMLXS_PORT_LOCK); + return (0); -} /* emlxs_cmpl_unreg_vpi() */ +} /* emlxs_unreg_vpi_mbcmpl() */ +/* SLI3 */ extern uint32_t emlxs_mb_unreg_vpi(emlxs_port_t *port) { emlxs_hba_t *hba = HBA; MAILBOXQ *mbq; MAILBOX *mb; - MAILBOX4 *mb4; - VFIobj_t *vfip; - FCFIobj_t *fcfp; int rval; + if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) { + return (1); + } + mutex_enter(&EMLXS_PORT_LOCK); - if (!(port->flag & EMLXS_PORT_REGISTERED)) { + if (!(port->flag & EMLXS_PORT_REG_VPI) || + !(port->flag & EMLXS_PORT_REG_VPI_CMPL)) { + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi:%d failed. Not registered. flag=%x", + port->vpi, port->flag); + mutex_exit(&EMLXS_PORT_LOCK); return (0); } if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi:%d failed. Unable to allocate mbox.", + port->vpi); + mutex_exit(&EMLXS_PORT_LOCK); return (1); } - port->flag &= ~EMLXS_PORT_REGISTERED; + port->flag &= ~EMLXS_PORT_REG_VPI; mutex_exit(&EMLXS_PORT_LOCK); - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - mb4 = (MAILBOX4 *)mbq->mbox; - bzero((void *)mb4, MAILBOX_CMD_SLI4_BSIZE); - mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */ - mb4->un.varUnRegVPI4.index = port->vpi + hba->vpi_base; - mb4->mbxCommand = MBX_UNREG_VPI; - mb4->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = emlxs_cmpl_unreg_vpi; - } else { - mb = (MAILBOX *)mbq->mbox; - bzero((void *)mb, MAILBOX_CMD_BSIZE); - mb->un.varUnregVpi.vpi = port->vpi + hba->vpi_base; - mb->mbxCommand = MBX_UNREG_VPI; - mb->mbxOwner = OWN_HOST; - mbq->mbox_cmpl = NULL; /* no cmpl needed */ - } - - rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); - if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi:%d", port->vpi); - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - if ((vfip = port->VFIp) != NULL) { + mb = (MAILBOX *)mbq->mbox; + bzero((void *)mb, MAILBOX_CMD_BSIZE); + mb->un.varUnregVpi.vpi = port->vpi; + mb->mbxCommand = MBX_UNREG_VPI; + mb->mbxOwner = OWN_HOST; - fcfp = vfip->FCFIp; - if (port == fcfp->fcf_vpi) { - fcfp->fcf_vpi = NULL; - } + mbq->mbox_cmpl = emlxs_unreg_vpi_mbcmpl; + mbq->context = NULL; + mbq->port = (void *)port; - mutex_enter(&EMLXS_PORT_LOCK); - vfip->outstandingVPIs--; - if ((vfip->outstandingVPIs == 0) && - (hba->state == FC_LINK_DOWN)) { - mutex_exit(&EMLXS_PORT_LOCK); + rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); + if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_vpi:%d failed. Unable to send request.", + port->vpi); - /* No more VPIs so unreg the VFI */ - (void) emlxs_mb_unreg_vfi(hba, vfip); - } else { - mutex_exit(&EMLXS_PORT_LOCK); - } - } + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + return (1); } + return (0); } /* emlxs_mb_unreg_vpi() */ @@ -3755,6 +2645,8 @@ emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_CONFIG_FARP; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; + } /* emlxs_mb_config_farp() */ @@ -3777,6 +2669,8 @@ emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand = MBX_READ_CONFIG; mb->mbxOwner = OWN_HOST; mbq->mbox_cmpl = NULL; /* no cmpl needed */ + mbq->port = (void *)&PPORT; + } /* emlxs_mb_read_config() */ @@ -3886,7 +2780,7 @@ emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo) mbq->next = 0; mutex_enter(&EMLXS_MBOX_LOCK); - hba->mbox_mbq = (uint8_t *)mbq; + hba->mbox_mbq = (void *)mbq; mutex_exit(&EMLXS_MBOX_LOCK); if (mbq->nonembed) { @@ -3917,7 +2811,6 @@ emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) MAILBOXQ *mbox_mbq; MAILBOX *mbox; uint32_t mbox_queue_flag; - emlxs_ub_priv_t *ub_priv; mutex_enter(&EMLXS_PORT_LOCK); @@ -3949,7 +2842,7 @@ emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) mbox_iocbq = NULL; } - hba->mbox_mbq = 0; + hba->mbox_mbq = NULL; hba->mbox_queue_flag = 0; hba->mbox_timer = 0; mutex_exit(&EMLXS_MBOX_LOCK); @@ -3959,15 +2852,15 @@ emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) if (mbox_queue_flag == MBX_NOWAIT) { /* Check for deferred MBUF cleanup */ if (mbox_bp) { - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp); + emlxs_mem_put(hba, MEM_BUF, (void *)mbox_bp); } if (mbox_nonembed) { - (void) emlxs_mem_put(hba, MEM_BUF, - (uint8_t *)mbox_nonembed); + emlxs_mem_put(hba, MEM_BUF, + (void *)mbox_nonembed); } if (mbox_mbq) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox_mbq); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox_mbq); } } else { /* MBX_WAIT */ if (mbox_mbq) { @@ -3986,7 +2879,7 @@ emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) } mbox = (MAILBOX *)mbox_mbq; - mbox->mbxStatus = mbxStatus; + mbox->mbxStatus = (uint16_t)mbxStatus; /* Mark mailbox complete */ mbox_mbq->flag |= MBQ_COMPLETED; @@ -4009,51 +2902,87 @@ emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus) } #endif /* SFCT_SUPPORT */ + emlxs_mb_deferred_cmpl(port, mbxStatus, mbox_sbp, mbox_ubp, mbox_iocbq); + + return; + +} /* emlxs_mb_fini() */ + + +extern void +emlxs_mb_deferred_cmpl(emlxs_port_t *port, uint32_t mbxStatus, emlxs_buf_t *sbp, + fc_unsol_buf_t *ubp, IOCBQ *iocbq) +{ + emlxs_hba_t *hba = HBA; + emlxs_ub_priv_t *ub_priv; + +#ifdef SFCT_SUPPORT + if ((mbxStatus == MBX_SUCCESS) && sbp && sbp->fct_cmd) { + emlxs_buf_t *cmd_sbp = sbp; + + if ((cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) && + (cmd_sbp->node)) { + + mutex_enter(&EMLXS_PKT_LOCK); + cmd_sbp->fct_flags |= EMLXS_FCT_REGISTERED; + cv_broadcast(&EMLXS_PKT_CV); + mutex_exit(&EMLXS_PKT_LOCK); + + sbp = NULL; + } + } +#endif /* SFCT_SUPPORT */ + /* Check for deferred pkt completion */ - if (mbox_sbp) { + if (sbp) { if (mbxStatus != MBX_SUCCESS) { /* Set error status */ - mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID; - emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT, + sbp->pkt_flags &= ~PACKET_STATE_VALID; + emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, IOERR_NO_RESOURCES, 1); } - emlxs_pkt_complete(mbox_sbp, -1, 0, 1); + emlxs_pkt_complete(sbp, -1, 0, 1); } /* Check for deferred ub completion */ - if (mbox_ubp) { - ub_priv = mbox_ubp->ub_fca_private; - port = ub_priv->port; + if (ubp) { + ub_priv = ubp->ub_fca_private; - emlxs_ub_callback(port, mbox_ubp); + if (mbxStatus == MBX_SUCCESS) { + emlxs_ub_callback(ub_priv->port, ubp); + } else { + (void) emlxs_fca_ub_release(ub_priv->port, 1, + &ubp->ub_token); + } } - /* Special handling for vport PLOGI */ - if (mbox_iocbq == (IOCBQ *)1) { - mbox_iocbq = NULL; + /* Special handling for restricted login */ + if (iocbq == (IOCBQ *)1) { + iocbq = NULL; } /* Check for deferred iocb tx */ - if (mbox_iocbq) { + if (iocbq) { /* Check for driver special codes */ /* These indicate the mailbox is being flushed */ if (mbxStatus >= MBX_DRIVER_RESERVED) { /* Set the error status and return it */ - mbox_iocbq->iocb.ULPSTATUS = IOSTAT_LOCAL_REJECT; - mbox_iocbq->iocb.un.grsp.perr.statLocalError = + iocbq->iocb.ULPSTATUS = IOSTAT_LOCAL_REJECT; + iocbq->iocb.un.grsp.perr.statLocalError = IOERR_ABORT_REQUESTED; - emlxs_proc_channel_event(hba, mbox_iocbq->channel, - mbox_iocbq); + emlxs_proc_channel_event(hba, iocbq->channel, + iocbq); } else { - EMLXS_SLI_ISSUE_IOCB_CMD(hba, mbox_iocbq->channel, - mbox_iocbq); + EMLXS_SLI_ISSUE_IOCB_CMD(hba, iocbq->channel, + iocbq); } } + return; -} /* emlxs_mb_fini() */ +} /* emlxs_mb_deferred_cmpl() */ extern void @@ -4072,7 +3001,7 @@ emlxs_mb_flush(emlxs_hba_t *hba) while (mbq = (MAILBOXQ *)emlxs_mb_get(hba)) { mutex_enter(&EMLXS_MBOX_LOCK); hba->mbox_queue_flag = MBX_NOWAIT; - hba->mbox_mbq = (uint8_t *)mbq; + hba->mbox_mbq = (void *)mbq; mutex_exit(&EMLXS_MBOX_LOCK); emlxs_mb_fini(hba, NULL, mbxStatus); diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c index 493baee8c2..ec7998eb6b 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -55,7 +55,7 @@ emlxs_mem_alloc_buffer(emlxs_hba_t *hba) */ cnt = cfg[CFG_NUM_IOTAGS].current; if (cnt) { - hba->max_iotag = cnt; + hba->max_iotag = (uint16_t)cnt; } /* ioatg 0 is not used, iotags 1 thru max_iotag-1 are used */ @@ -297,19 +297,19 @@ emlxs_mem_free_buffer(emlxs_hba_t *hba) if ((mp = emlxs_mem_get_vaddr(hba, rp, addr))) { if (j == hba->channel_els) { - (void) emlxs_mem_put(hba, - MEM_ELSBUF, (uint8_t *)mp); + emlxs_mem_put(hba, + MEM_ELSBUF, (void *)mp); } else if (j == hba->channel_ct) { - (void) emlxs_mem_put(hba, - MEM_CTBUF, (uint8_t *)mp); + emlxs_mem_put(hba, + MEM_CTBUF, (void *)mp); } else if (j == hba->channel_ip) { - (void) emlxs_mem_put(hba, - MEM_IPBUF, (uint8_t *)mp); + emlxs_mem_put(hba, + MEM_IPBUF, (void *)mp); } #ifdef SFCT_SUPPORT else if (j == hba->CHANNEL_FCT) { - (void) emlxs_mem_put(hba, - MEM_FCTBUF, (uint8_t *)mp); + emlxs_mem_put(hba, + MEM_FCTBUF, (void *)mp); } #endif /* SFCT_SUPPORT */ @@ -434,7 +434,7 @@ emlxs_mem_pool_alloc(emlxs_hba_t *hba, MEMSEG *seg) /* Free the mp object */ bzero(buf_info, sizeof (MBUF_INFO)); buf_info->size = sizeof (MATCHMAP); - buf_info->virt = (uint32_t *)mp; + buf_info->virt = (void *)mp; emlxs_mem_free(hba, buf_info); goto failed; @@ -572,7 +572,7 @@ emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg) bzero(buf_info, sizeof (MBUF_INFO)); buf_info->size = sizeof (MATCHMAP); - buf_info->virt = (uint32_t *)mp; + buf_info->virt = (void *)mp; emlxs_mem_free(hba, buf_info); } @@ -592,7 +592,7 @@ emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg) bzero(buf_info, sizeof (MBUF_INFO)); buf_info->size = sizeof (MATCHMAP); - buf_info->virt = (uint32_t *)mp; + buf_info->virt = (void *)mp; emlxs_mem_free(hba, buf_info); } @@ -601,13 +601,13 @@ emlxs_mem_pool_free(emlxs_hba_t *hba, MEMSEG *seg) } /* emlxs_mem_pool_free() */ -extern uint8_t * +extern void * emlxs_mem_pool_get(emlxs_hba_t *hba, MEMSEG *seg, uint32_t priority) { - emlxs_port_t *port = &PPORT; - uint8_t *bp = NULL; - MATCHMAP *mp; - uint32_t free; + emlxs_port_t *port = &PPORT; + void *bp = NULL; + MATCHMAP *mp; + uint32_t free; mutex_enter(&EMLXS_MEMGET_LOCK); @@ -684,13 +684,13 @@ top: } /* emlxs_mem_pool_get() */ -extern MEMSEG * -emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) +extern void +emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, void *bp) { - emlxs_port_t *port = &PPORT; - MATCHMAP *mp; - uint8_t *base; - uint8_t *end; + emlxs_port_t *port = &PPORT; + MATCHMAP *mp; + void *base; + void *end; /* Free the pool object */ mutex_enter(&EMLXS_MEMPUT_LOCK); @@ -698,7 +698,7 @@ emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) /* Check if memory segment destroyed! */ if (seg->fc_total_memsize == 0) { mutex_exit(&EMLXS_MEMPUT_LOCK); - return (NULL); + return; } /* Check if buffer was just freed */ @@ -707,7 +707,7 @@ emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) "%s: Freeing free object: bp=%p", seg->fc_label, bp); mutex_exit(&EMLXS_MEMPUT_LOCK); - return (NULL); + return; } /* Validate the buffer belongs to this pool */ @@ -728,12 +728,13 @@ emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); - return (NULL); + return; } } else { /* Vmem_pool */ base = seg->fc_memstart_virt; - end = seg->fc_memstart_virt + seg->fc_total_memsize; + end = (void *)((uint8_t *)seg->fc_memstart_virt + + seg->fc_total_memsize); if (bp < base || bp >= end) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pool_error_msg, @@ -748,7 +749,7 @@ emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); - return (NULL); + return; } } @@ -757,15 +758,15 @@ emlxs_mem_pool_put(emlxs_hba_t *hba, MEMSEG *seg, uint8_t *bp) seg->fc_memput_ptr = bp; seg->fc_memput_cnt = 1; } else { - *((uint8_t **)(seg->fc_memput_end)) = bp; + *((void **)(seg->fc_memput_end)) = bp; seg->fc_memput_cnt++; } seg->fc_memput_end = bp; - *((uint8_t **)(bp)) = NULL; + *((void **)(bp)) = NULL; mutex_exit(&EMLXS_MEMPUT_LOCK); - return (seg); + return; } /* emlxs_mem_pool_put() */ @@ -810,7 +811,7 @@ emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size) /* Free the mp object */ bzero(buf_info, sizeof (MBUF_INFO)); buf_info->size = sizeof (MATCHMAP); - buf_info->virt = (uint32_t *)mp; + buf_info->virt = (void *)mp; emlxs_mem_free(hba, buf_info); return (0); @@ -831,7 +832,7 @@ emlxs_mem_buf_alloc(emlxs_hba_t *hba, uint32_t size) } /* emlxs_mem_buf_alloc() */ -extern MATCHMAP * +extern void emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp) { MBUF_INFO bufinfo; @@ -840,7 +841,7 @@ emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp) buf_info = &bufinfo; if (!(mp->flag & MAP_BUF_ALLOCATED)) { - return (NULL); + return; } bzero(buf_info, sizeof (MBUF_INFO)); @@ -854,23 +855,23 @@ emlxs_mem_buf_free(emlxs_hba_t *hba, MATCHMAP *mp) bzero(buf_info, sizeof (MBUF_INFO)); buf_info->size = sizeof (MATCHMAP); - buf_info->virt = (uint32_t *)mp; + buf_info->virt = (void *)mp; emlxs_mem_free(hba, buf_info); - return (mp); + return; } /* emlxs_mem_buf_free() */ -extern uint8_t * +extern void * emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id, uint32_t priority) { - emlxs_port_t *port = &PPORT; - uint8_t *bp; - MAILBOXQ *mbq; - IOCBQ *iocbq; - NODELIST *node; - MEMSEG *seg; + emlxs_port_t *port = &PPORT; + void *bp; + MAILBOXQ *mbq; + IOCBQ *iocbq; + NODELIST *node; + MEMSEG *seg; if (seg_id >= FC_MAX_SEG) { @@ -909,15 +910,15 @@ emlxs_mem_get(emlxs_hba_t *hba, uint32_t seg_id, uint32_t priority) } /* emlxs_mem_get() */ -extern uint8_t * -emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) +extern void +emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, void *bp) { - emlxs_port_t *port = &PPORT; - MAILBOXQ *mbq; - IOCBQ *iocbq; - NODELIST *node; - MEMSEG *seg; - MATCHMAP *mp; + emlxs_port_t *port = &PPORT; + MAILBOXQ *mbq; + IOCBQ *iocbq; + NODELIST *node; + MEMSEG *seg; + MATCHMAP *mp; if (seg_id >= FC_MAX_SEG) { @@ -925,7 +926,7 @@ emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) "emlxs_mem_put: Invalid segment id = %d: bp=%p", seg_id, bp); - return (NULL); + return; } seg = &hba->memseg[seg_id]; @@ -935,7 +936,7 @@ emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) mbq = (MAILBOXQ *)bp; if (!(mbq->flag & MBQ_POOL_ALLOCATED)) { - return (NULL); + return; } break; @@ -943,13 +944,13 @@ emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) iocbq = (IOCBQ *)bp; if (!(iocbq->flag & IOCB_POOL_ALLOCATED)) { - return (NULL); + return; } /* Any IOCBQ with a packet attached did not come */ /* from our pool */ if (iocbq->sbp) { - return (NULL); + return; } break; @@ -957,7 +958,7 @@ emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) node = (NODELIST *)bp; if (!(node->flag & NODE_POOL_ALLOCATED)) { - return (NULL); + return; } break; @@ -965,25 +966,24 @@ emlxs_mem_put(emlxs_hba_t *hba, uint32_t seg_id, uint8_t *bp) mp = (MATCHMAP *)bp; if (mp->flag & MAP_BUF_ALLOCATED) { - return ((uint8_t *)emlxs_mem_buf_free(hba, mp)); + emlxs_mem_buf_free(hba, mp); + return; } if (mp->flag & MAP_TABLE_ALLOCATED) { - return (bp); + return; } if (!(mp->flag & MAP_POOL_ALLOCATED)) { - return (NULL); + return; } break; } /* Free a buffer to the pool */ - if (emlxs_mem_pool_put(hba, seg, bp) == NULL) { - return (NULL); - } + emlxs_mem_pool_put(hba, seg, bp); - return (bp); + return; } /* emlxs_mem_put() */ @@ -1011,11 +1011,11 @@ emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp) prev->fc_mptr = mp->fc_mptr; } - if (rp->fc_mpon == (uint8_t *)mp) { - rp->fc_mpon = (uint8_t *)prev; + if (rp->fc_mpon == mp) { + rp->fc_mpon = (void *)prev; } - mp->fc_mptr = 0; + mp->fc_mptr = NULL; EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, DDI_DMA_SYNC_FORKERNEL); @@ -1046,11 +1046,11 @@ emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp) prev->fc_mptr = mp->fc_mptr; } - if (rp->fc_mpon == (uint8_t *)mp) { - rp->fc_mpon = (uint8_t *)prev; + if (rp->fc_mpon == mp) { + rp->fc_mpon = (void *)prev; } - mp->fc_mptr = 0; + mp->fc_mptr = NULL; EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, DDI_DMA_SYNC_FORKERNEL); @@ -1081,11 +1081,11 @@ emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp) prev->fc_mptr = mp->fc_mptr; } - if (rp->fc_mpon == (uint8_t *)mp) { - rp->fc_mpon = (uint8_t *)prev; + if (rp->fc_mpon == mp) { + rp->fc_mpon = (void *)prev; } - mp->fc_mptr = 0; + mp->fc_mptr = NULL; EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, DDI_DMA_SYNC_FORKERNEL); @@ -1116,11 +1116,11 @@ emlxs_mem_get_vaddr(emlxs_hba_t *hba, RING *rp, uint64_t mapbp) prev->fc_mptr = mp->fc_mptr; } - if (rp->fc_mpon == (uint8_t *)mp) { - rp->fc_mpon = (uint8_t *)prev; + if (rp->fc_mpon == mp) { + rp->fc_mpon = (void *)prev; } - mp->fc_mptr = 0; + mp->fc_mptr = NULL; EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size, DDI_DMA_SYNC_FORKERNEL); @@ -1161,14 +1161,14 @@ emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp, * fc_mpoff is pointer head of the list. * fc_mpon is pointer tail of the list. */ - mp->fc_mptr = 0; + mp->fc_mptr = NULL; if (rp->fc_mpoff == 0) { - rp->fc_mpoff = (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + rp->fc_mpoff = (void *)mp; + rp->fc_mpon = (void *)mp; } else { ((MATCHMAP *)(rp->fc_mpon))->fc_mptr = - (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + (void *)mp; + rp->fc_mpon = (void *)mp; } if (hba->flag & FC_SLIM2_MODE) { @@ -1190,14 +1190,14 @@ emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp, * fc_mpoff is pointer head of the list. * fc_mpon is pointer tail of the list. */ - mp->fc_mptr = 0; + mp->fc_mptr = NULL; if (rp->fc_mpoff == 0) { - rp->fc_mpoff = (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + rp->fc_mpoff = (void *)mp; + rp->fc_mpon = (void *)mp; } else { ((MATCHMAP *)(rp->fc_mpon))->fc_mptr = - (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + (void *)mp; + rp->fc_mpon = (void *)mp; } if (hba->flag & FC_SLIM2_MODE) { @@ -1219,14 +1219,14 @@ emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp, * fc_mpoff is pointer head of the list. * fc_mpon is pointer tail of the list. */ - mp->fc_mptr = 0; + mp->fc_mptr = NULL; if (rp->fc_mpoff == 0) { - rp->fc_mpoff = (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + rp->fc_mpoff = (void *)mp; + rp->fc_mpon = (void *)mp; } else { ((MATCHMAP *)(rp->fc_mpon))->fc_mptr = - (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + (void *)mp; + rp->fc_mpon = (void *)mp; } if (hba->flag & FC_SLIM2_MODE) { @@ -1247,14 +1247,14 @@ emlxs_mem_map_vaddr(emlxs_hba_t *hba, RING *rp, MATCHMAP *mp, * fc_mpoff is pointer head of the list. * fc_mpon is pointer tail of the list. */ - mp->fc_mptr = 0; + mp->fc_mptr = NULL; if (rp->fc_mpoff == 0) { - rp->fc_mpoff = (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + rp->fc_mpoff = (void *)mp; + rp->fc_mpon = (void *)mp; } else { ((MATCHMAP *)(rp->fc_mpon))->fc_mptr = - (uint8_t *)mp; - rp->fc_mpon = (uint8_t *)mp; + (void *)mp; + rp->fc_mpon = (void *)mp; } if (hba->flag & FC_SLIM2_MODE) { @@ -1302,7 +1302,7 @@ emlxs_hbq_alloc(emlxs_hba_t *hba, uint32_t hbq_id) return (ENOMEM); } - hbq->HBQ_host_buf.virt = (void *)buf_info->virt; + hbq->HBQ_host_buf.virt = buf_info->virt; hbq->HBQ_host_buf.phys = buf_info->phys; hbq->HBQ_host_buf.data_handle = buf_info->data_handle; hbq->HBQ_host_buf.dma_handle = buf_info->dma_handle; diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_msg.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_msg.c index d7edaf3f86..2286fbbc77 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_msg.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_msg.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -28,10 +28,6 @@ #define DEF_MSG_STRUCT /* Needed for emlxs_messages.h in emlxs_msg.h */ #include <emlxs.h> - -/* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ -EMLXS_MSG_DEF(EMLXS_MSG_C); - uint32_t emlxs_log_size = 2048; uint32_t emlxs_log_debugs = 0x7FFFFFFF; uint32_t emlxs_log_notices = 0xFFFFFFFF; @@ -49,12 +45,6 @@ emlxs_msg_log_create(emlxs_hba_t *hba) emlxs_msg_log_t *log = &LOG; uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size; char buf[40]; -#ifdef MSI_SUPPORT - ddi_intr_handle_t handle; - uint32_t intr_pri; - int32_t actual; - uint32_t ret; -#endif /* MSI_SUPPORT */ ddi_iblock_cookie_t iblock; /* Check if log is already created */ @@ -87,55 +77,43 @@ emlxs_msg_log_create(emlxs_hba_t *hba) } #ifdef MSI_SUPPORT else { - /* Allocate a temporary interrupt handle */ - actual = 0; - ret = - ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED, - EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL); - - if (ret != DDI_SUCCESS || actual == 0) { - cmn_err(CE_WARN, - "?%s%d: Unable to allocate temporary interrupt " - "handle. ret=%d actual=%d", DRIVER_NAME, - hba->ddiinst, ret, actual); - - /* Free the log buffer */ - kmem_free(log->entry, size); - bzero(log, sizeof (emlxs_msg_log_t)); - - return (0); - } + /* Create the temporary log mutex lock */ + mutex_init(&log->lock, buf, MUTEX_DRIVER, NULL); + } +#endif - /* Get the current interrupt priority */ - ret = ddi_intr_get_pri(handle, &intr_pri); + return (1); - if (ret != DDI_SUCCESS) { - cmn_err(CE_WARN, - "?%s%d: Unable to get interrupt priority. ret=%d", - DRIVER_NAME, hba->ddiinst, ret); +} /* emlxs_msg_log_create() */ - /* Free the log buffer */ - kmem_free(log->entry, size); - bzero(log, sizeof (emlxs_msg_log_t)); - return (0); - } +void +emlxs_msg_lock_reinit(emlxs_hba_t *hba) +{ + emlxs_msg_log_t *log = &LOG; + char buf[40]; - /* Create the log mutex lock */ - mutex_init(&log->lock, buf, MUTEX_DRIVER, - (void *)((unsigned long)intr_pri)); + /* Check if log is already destroyed */ + if (!log->entry) { + cmn_err(CE_WARN, + "?%s%d: message log already destroyed. log=%p", + DRIVER_NAME, hba->ddiinst, (void *)log); - /* Free the temporary handle */ - (void) ddi_intr_free(handle); + return; } -#endif - return (1); + /* Destroy the temporary lock */ + mutex_destroy(&log->lock); -} /* emlxs_msg_log_create() */ + /* Re-create the log mutex lock */ + (void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst); + mutex_init(&log->lock, buf, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg)); + + return; +} /* emlxs_msg_lock_reinit() */ -uint32_t +void emlxs_msg_log_destroy(emlxs_hba_t *hba) { emlxs_msg_log_t *log = &LOG; @@ -147,7 +125,7 @@ emlxs_msg_log_destroy(emlxs_hba_t *hba) "?%s%d: message log already destroyed. log=%p", DRIVER_NAME, hba->ddiinst, (void *)log); - return (1); + return; } /* Destroy the lock */ @@ -160,7 +138,7 @@ emlxs_msg_log_destroy(emlxs_hba_t *hba) /* Clear the log */ bzero(log, sizeof (emlxs_msg_log_t)); - return (1); + return; } /* emlxs_msg_log_destroy() */ diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_node.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_node.c index 96c357d67d..6da42b02bd 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_node.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_node.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -205,7 +205,7 @@ emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) mutex_exit(&EMLXS_TX_CHANNEL_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, - "node=%p did=%06x %s. Flushing.", ndlp, ndlp->nlp_DID, + "node=%p did=%06x channel=%d. Flushing.", ndlp, ndlp->nlp_DID, channelno); /* Flush tx queue for this channel */ @@ -289,16 +289,12 @@ emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) mutex_exit(&EMLXS_TX_CHANNEL_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg, - "node=%p did=%06x channel=%d", ndlp, ndlp->nlp_DID, channelno); + "node=%p did=%06x rpi=%x channel=%d", ndlp, ndlp->nlp_DID, + ndlp->nlp_Rpi, channelno); /* If link attention needs to be cleared */ if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) { if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - /* re Think this code path. For SLI4 channel fcp == els */ - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d", - ndlp, ndlp->nlp_DID, channelno); - goto done; } @@ -338,8 +334,8 @@ emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) */ if (hba->state != FC_LINK_UP) { mutex_exit(&EMLXS_PORT_LOCK); - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox); goto done; } @@ -352,8 +348,8 @@ emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox); } } else { /* Close the node and try again */ @@ -661,7 +657,7 @@ emlxs_node_find_index(emlxs_port_t *port, uint32_t index, /* no match found */ return ((NODELIST *)0); -} /* emlxs_node_find_wwpn() */ +} /* emlxs_node_find_index() */ extern uint32_t @@ -696,7 +692,7 @@ emlxs_node_destroy_all(emlxs_port_t *port) emlxs_hba_t *hba = HBA; NODELIST *next; NODELIST *ndlp; - RPIobj_t *rp; + RPIobj_t *rpip; uint8_t *wwn; uint32_t i; @@ -726,17 +722,16 @@ emlxs_node_destroy_all(emlxs_port_t *port) (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); /* Break Node/RPI binding */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - rp = EMLXS_NODE_TO_RPI(hba, ndlp); - ndlp->RPIp = NULL; + if (ndlp->rpip) { + rpip = ndlp->rpip; - if (rp) { - rp->node = NULL; - (void) emlxs_sli4_free_rpi(hba, rp); - } + ndlp->rpip = NULL; + rpip->node = NULL; + + (void) emlxs_rpi_free_notify(port, rpip); } - (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); + emlxs_mem_put(hba, MEM_NLP, (void *)ndlp); ndlp = next; } @@ -760,14 +755,158 @@ emlxs_node_destroy_all(emlxs_port_t *port) } /* emlxs_node_destroy_all() */ +extern NODELIST * +emlxs_node_create(emlxs_port_t *port, uint32_t did, uint32_t rpi, SERV_PARM *sp) +{ + emlxs_hba_t *hba = HBA; + NODELIST *ndlp; + uint8_t *wwn; + emlxs_vvl_fmt_t vvl; + RPIobj_t *rpip; + + ndlp = emlxs_node_find_did(port, did); + + /* Update the node */ + if (ndlp) { + rw_enter(&port->node_rwlock, RW_WRITER); + + ndlp->nlp_Rpi = (uint16_t)rpi; + ndlp->nlp_DID = did; + + bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, + sizeof (SERV_PARM)); + + bcopy((uint8_t *)&sp->nodeName, + (uint8_t *)&ndlp->nlp_nodename, + sizeof (NAME_TYPE)); + + bcopy((uint8_t *)&sp->portName, + (uint8_t *)&ndlp->nlp_portname, + sizeof (NAME_TYPE)); + + /* Add Node/RPI binding */ + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + rpip = emlxs_rpi_find(port, rpi); + + if (rpip) { + rpip->node = ndlp; + ndlp->rpip = rpip; + } else { + ndlp->rpip = NULL; + + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_node_create_msg, + "Unable to find RPI. did=%x rpi=%x", + did, rpi); + } + } else { + ndlp->rpip = NULL; + } + rw_exit(&port->node_rwlock); + + wwn = (uint8_t *)&ndlp->nlp_portname; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg, + "node=%p did=%06x rpi=%x " + "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", + ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], + wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); + + goto done; + } + + /* Allocate a new node */ + ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0); + + if (ndlp) { + rw_enter(&port->node_rwlock, RW_WRITER); + + ndlp->nlp_Rpi = (uint16_t)rpi; + ndlp->nlp_DID = did; + + bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm, + sizeof (SERV_PARM)); + + bcopy((uint8_t *)&sp->nodeName, + (uint8_t *)&ndlp->nlp_nodename, + sizeof (NAME_TYPE)); + + bcopy((uint8_t *)&sp->portName, + (uint8_t *)&ndlp->nlp_portname, + sizeof (NAME_TYPE)); + + ndlp->nlp_active = 1; + ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED; + ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED; + ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED; + ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED; + + /* Add Node/RPI binding */ + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + rpip = emlxs_rpi_find(port, rpi); + + if (rpip) { + rpip->node = ndlp; + ndlp->rpip = rpip; + } else { + ndlp->rpip = NULL; + + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_node_create_msg, + "Unable to find RPI. did=%x rpi=%x", + did, rpi); + } + } else { + ndlp->rpip = NULL; + } + rw_exit(&port->node_rwlock); + + /* Add the node */ + emlxs_node_add(port, ndlp); + + goto done; + } + + wwn = (uint8_t *)&sp->portName; + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_node_create_failed_msg, + "Unable to allocate node. did=%06x " + "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", + did, wwn[0], wwn[1], wwn[2], + wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); + + return (NULL); + +done: + if (sp->VALID_VENDOR_VERSION) { + bcopy((caddr_t *)&sp->vendorVersion[0], + (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t)); + + vvl.un0.word0 = LE_SWAP32(vvl.un0.word0); + vvl.un1.word1 = LE_SWAP32(vvl.un1.word1); + + if ((vvl.un0.w0.oui == 0x0000C9) && + (vvl.un1.w1.vport)) { + ndlp->nlp_fcp_info |= NLP_EMLX_VPORT; + } + } + + /* Open the node */ + emlxs_node_open(port, ndlp, hba->channel_ct); + emlxs_node_open(port, ndlp, hba->channel_els); + emlxs_node_open(port, ndlp, hba->channel_ip); + emlxs_node_open(port, ndlp, hba->channel_fcp); + + return (ndlp); + +} /* emlxs_node_create() */ + + extern void emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp) { - emlxs_hba_t *hba = HBA; NODELIST *np; uint8_t *wwn; uint32_t hash; - RPIobj_t *rp; rw_enter(&port->node_rwlock, RW_WRITER); hash = EMLXS_DID_HASH(ndlp->nlp_DID); @@ -790,20 +929,6 @@ emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp) "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count); - /* Add Node/RPI binding */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi); - - if (rp) { - rp->node = ndlp; - ndlp->RPIp = rp; - } else { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, - "Unable to find RPI! did=%x rpi=%x", - ndlp->nlp_DID, ndlp->nlp_Rpi); - } - } - rw_exit(&port->node_rwlock); return; @@ -817,7 +942,7 @@ emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp) emlxs_hba_t *hba = HBA; NODELIST *np; NODELIST *prevp; - RPIobj_t *rp; + RPIobj_t *rpip; uint8_t *wwn; uint32_t hash; @@ -850,17 +975,16 @@ emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp) ndlp->nlp_active = 0; /* Break Node/RPI binding */ - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - rp = EMLXS_NODE_TO_RPI(hba, ndlp); - ndlp->RPIp = NULL; + if (ndlp->rpip) { + rpip = ndlp->rpip; - if (rp) { - rp->node = NULL; - (void) emlxs_sli4_free_rpi(hba, rp); - } + ndlp->rpip = NULL; + rpip->node = NULL; + + (void) emlxs_rpi_free_notify(port, rpip); } - (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); + emlxs_mem_put(hba, MEM_NLP, (void *)ndlp); break; } diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_pkt.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_pkt.c index e6453c6854..c23adc18d7 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_pkt.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_pkt.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -84,7 +84,7 @@ emlxs_pkt_send(fc_packet_t *pkt, uint32_t now) int32_t rval; if (now) { - rval = emlxs_transport((opaque_t)port, pkt); + rval = emlxs_fca_transport((opaque_t)port, pkt); } else { /* Spawn a thread to send the pkt */ emlxs_thread_spawn(hba, emlxs_pkt_thread, (char *)pkt, NULL); @@ -102,7 +102,7 @@ emlxs_pkt_free(fc_packet_t *pkt) { emlxs_port_t *port = (emlxs_port_t *)pkt->pkt_ulp_private; - (void) emlxs_pkt_uninit((opaque_t)port, pkt); + (void) emlxs_fca_pkt_uninit((opaque_t)port, pkt); if (pkt->pkt_datalen) { (void) ddi_dma_unbind_handle(pkt->pkt_data_dma); @@ -387,7 +387,7 @@ emlxs_pkt_alloc(emlxs_port_t *port, uint32_t cmdlen, uint32_t rsplen, sbp = PKT2PRIV(pkt); bzero((void *)sbp, sizeof (emlxs_buf_t)); - mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg); + mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg)); sbp->pkt_flags = PACKET_VALID | PACKET_ULP_OWNED | PACKET_ALLOCATED; sbp->port = port; sbp->pkt = pkt; diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c index 58bf876d1e..18a63d73f0 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c @@ -34,7 +34,6 @@ static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba); static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, uint32_t ha_copy); -static int emlxs_sli3_mb_handle_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq); #ifdef SFCT_SUPPORT static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); #endif /* SFCT_SUPPORT */ @@ -111,8 +110,7 @@ static void emlxs_sli3_enable_intr(emlxs_hba_t *hba); static void emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att); -static uint32_t emlxs_reset_ring(emlxs_hba_t *hba, - uint32_t ringno); + static void emlxs_handle_ff_error(emlxs_hba_t *hba); static uint32_t emlxs_handle_mb_event(emlxs_hba_t *hba); @@ -127,7 +125,7 @@ static void emlxs_enable_latt(emlxs_hba_t *hba); static uint32_t emlxs_check_attention(emlxs_hba_t *hba); static uint32_t emlxs_get_attention(emlxs_hba_t *hba, - uint32_t msgid); + int32_t msgid); static void emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy); /* static int emlxs_handle_rcv_seq(emlxs_hba_t *hba, */ @@ -191,7 +189,7 @@ emlxs_sli3_online(emlxs_hba_t *hba) uint8_t *inptr; uint8_t *outptr; uint32_t status; - uint32_t i; + uint16_t i; uint32_t j; uint32_t read_rev_reset; uint32_t key = 0; @@ -216,12 +214,13 @@ emlxs_sli3_online(emlxs_hba_t *hba) (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); } - /* - * Get a buffer which will be used repeatedly for mailbox commands - */ - mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); + /* Set the fw_check flag */ + fw_check = cfg[CFG_FW_CHECK].current; - mb = (MAILBOX *)mbq; + if ((fw_check & 0x04) || + (hba->fw_flag & FW_UPDATE_KERNEL)) { + kern_update = 1; + } hba->mbox_queue_flag = 0; hba->sli.sli3.hc_copy = 0; @@ -230,13 +229,12 @@ emlxs_sli3_online(emlxs_hba_t *hba) hba->fc_altov = FF_DEF_ALTOV; hba->fc_arbtov = FF_DEF_ARBTOV; - /* Set the fw_check flag */ - fw_check = cfg[CFG_FW_CHECK].current; + /* + * Get a buffer which will be used repeatedly for mailbox commands + */ + mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); - if ((fw_check & 0x04) || - (hba->fw_flag & FW_UPDATE_KERNEL)) { - kern_update = 1; - } + mb = (MAILBOX *)mbq; reset: /* Initialize sli mode based on configuration parameter */ @@ -883,7 +881,7 @@ reset: } /* Save the link speed capabilities */ - vpd->link_speed = mb->un.varRdConfig.lmt; + vpd->link_speed = (uint16_t)mb->un.varRdConfig.lmt; emlxs_process_link_speed(hba); /* Set the max node count */ @@ -993,9 +991,9 @@ reset: } /* Free the buffers since we were polling */ - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); mp = NULL; - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); + emlxs_mem_put(hba, MEM_BUF, (void *)mp1); mp1 = NULL; hba->channel_fcp = FC_FCP_RING; @@ -1107,7 +1105,7 @@ reset: * We need to get login parameters for NID */ (void) emlxs_mb_read_sparam(hba, mbq); - mp = (MATCHMAP *)(mbq->bp); + mp = (MATCHMAP *)mbq->bp; if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "Unable to read parameters. Mailbox cmd=%x status=%x", @@ -1118,7 +1116,7 @@ reset: } /* Free the buffer since we were polling */ - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); mp = NULL; /* If no serial number in VPD data, then use the WWPN */ @@ -1160,7 +1158,7 @@ reset: * Make first attempt to set a port index * Check if this is a multifunction adapter */ - if ((vpd->port_index == -1) && + if ((vpd->port_index == (uint32_t)-1) && (hba->model_info.chip >= EMLXS_THOR_CHIP)) { char *buffer; int32_t i; @@ -1189,7 +1187,7 @@ reset: } /* Make final attempt to set a port index */ - if (vpd->port_index == -1) { + if (vpd->port_index == (uint32_t)-1) { dev_info_t *p_dip; dev_info_t *c_dip; @@ -1275,6 +1273,12 @@ reset: #ifdef MSI_SUPPORT /* Configure MSI map if required */ if (hba->intr_count > 1) { + + if (hba->intr_type == DDI_INTR_TYPE_MSIX) { + /* always start from 0 */ + hba->last_msiid = 0; + } + /* Reuse mbq from previous mbox */ bzero(mbq, sizeof (MAILBOXQ)); @@ -1336,6 +1340,16 @@ reset: msi_configured: + if ((hba->intr_count >= 1) && + (hba->sli_mode == EMLXS_HBA_SLI3_MODE)) { + /* intr_count is a sequence of msi id */ + /* Setup msi2chan[msi_id] */ + for (i = 0; i < hba->intr_count; i ++) { + hba->msi2chan[i] = i; + if (i >= hba->chan_count) + hba->msi2chan[i] = (i - hba->chan_count); + } + } #endif /* MSI_SUPPORT */ /* @@ -1462,9 +1476,7 @@ msi_configured: "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); } - - /* Reuse mbq from previous mbox */ - bzero(mbq, sizeof (MAILBOXQ)); + (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); /* * Setup and issue mailbox INITIALIZE LINK command @@ -1472,17 +1484,27 @@ msi_configured: * Do this only if persist-linkdown is not set */ if (cfg[CFG_PERSIST_LINKDOWN].current == 0) { + mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1); + if (mbq == NULL) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, + "Unable to allocate mailbox buffer."); + + rval = EIO; + goto failed; + } + emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current, cfg[CFG_LINK_SPEED].current); rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "Unable to initialize link. " \ "Mailbox cmd=%x status=%x", mb->mbxCommand, mb->mbxStatus); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); + mbq = NULL; rval = EIO; goto failed; } @@ -1499,9 +1521,9 @@ msi_configured: if (hba->state == FC_ERROR) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Adapter error.", mb->mbxCommand, - mb->mbxStatus); + "Adapter error."); + mbq = NULL; rval = EIO; goto failed; } @@ -1517,7 +1539,6 @@ msi_configured: * The leadvile driver will now handle the FLOGI at the driver level */ - (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); return (0); failed: @@ -1529,12 +1550,12 @@ failed: } if (mp) { - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); mp = NULL; } if (mp1) { - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); + emlxs_mem_put(hba, MEM_BUF, (void *)mp1); mp1 = NULL; } @@ -1698,7 +1719,7 @@ emlxs_sli3_map_hdw(emlxs_hba_t *hba) goto failed; } - hba->sli.sli3.slim2.virt = (uint8_t *)buf_info->virt; + hba->sli.sli3.slim2.virt = buf_info->virt; hba->sli.sli3.slim2.phys = buf_info->phys; hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE; hba->sli.sli3.slim2.data_handle = buf_info->data_handle; @@ -1784,11 +1805,11 @@ emlxs_sli3_unmap_hdw(emlxs_hba_t *hba) buf_info->flags = FC_MBUF_DMA; } - buf_info->virt = (uint32_t *)hba->sli.sli3.slim2.virt; + buf_info->virt = hba->sli.sli3.slim2.virt; buf_info->size = hba->sli.sli3.slim2.size; emlxs_mem_free(hba, buf_info); - hba->sli.sli3.slim2.virt = 0; + hba->sli.sli3.slim2.virt = NULL; } @@ -1803,7 +1824,7 @@ emlxs_sli3_hba_init(emlxs_hba_t *hba) emlxs_port_t *port = &PPORT; emlxs_port_t *vport; emlxs_config_t *cfg; - int32_t i; + uint16_t i; cfg = &CFG; i = 0; @@ -1884,6 +1905,10 @@ emlxs_sli3_hba_init(emlxs_hba_t *hba) vport = &VPORT(i); vport->hba = hba; vport->vpi = i; + vport->VPIobj.index = i; + vport->VPIobj.VPI = i; + vport->VPIobj.port = vport; + vport->VPIobj.state = VPI_STATE_OFFLINE; } /* @@ -2115,6 +2140,7 @@ done: vport->prev_did = 0; vport->lip_type = 0; bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); + bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM)); bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); vport->node_base.nlp_Rpi = 0; @@ -3048,7 +3074,7 @@ static uint32_t emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, uint32_t tmo) { - emlxs_port_t *port = &PPORT; + emlxs_port_t *port; SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; MAILBOX *mbox; MAILBOX *mb; @@ -3060,6 +3086,12 @@ emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, uint32_t tmo_local; MAILBOX *swpmb; + if (!mbq->port) { + mbq->port = &PPORT; + } + + port = (emlxs_port_t *)mbq->port; + mb = (MAILBOX *)mbq; swpmb = (MAILBOX *)&word0; @@ -3574,7 +3606,7 @@ emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, /* Initalize iocb */ iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid; - iocb->ULPIOTAG = iotag; + iocb->ULPIOTAG = (uint16_t)iotag; iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout); iocb->ULPOWNER = OWN_CHIP; iocb->ULPCLASS = cmd_sbp->class; @@ -3590,9 +3622,10 @@ emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) && (dbuf->db_data_size == - fct_task->task_expected_xfer_length)) + fct_task->task_expected_xfer_length)) { iocb->ULPCT = 0x1; /* enable auto-rsp AP feature */ + } } return (IOERR_SUCCESS); @@ -3770,13 +3803,12 @@ emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN; iocb->ULPCONTEXT = 0; - if (hba->sli_mode == 3) { + if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { if (hba->topology != TOPOLOGY_LOOP) { iocb->ULPCT = 0x1; } iocb->ULPCONTEXT = port->vpi; } - } else { HBASTATS.IpSeqIssued++; @@ -3861,17 +3893,20 @@ emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0; iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR; - if (hba->topology != TOPOLOGY_LOOP) { - cmd = *((uint32_t *)pkt->pkt_cmd); - cmd &= ELS_CMD_MASK; + if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { + if (hba->topology != TOPOLOGY_LOOP) { + cmd = *((uint32_t *)pkt->pkt_cmd); + cmd &= ELS_CMD_MASK; - if ((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) { - iocb->ULPCT = 0x2; - } else { - iocb->ULPCT = 0x1; + if ((cmd == ELS_CMD_FLOGI) || + (cmd == ELS_CMD_FDISC)) { + iocb->ULPCT = 0x2; + } else { + iocb->ULPCT = 0x1; + } } + iocb->ULPCONTEXT = port->vpi; } - iocb->ULPCONTEXT = port->vpi; } iocb->ULPIOTAG = iotag; iocb->ULPRSVDBYTE = @@ -4025,7 +4060,8 @@ emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) return (1); } - if ((hba->sli_mode < 3) || (sgllen > SLI3_MAX_BDE)) { + if ((hba->sli_mode < EMLXS_HBA_SLI3_MODE) || + (sgllen > SLI3_MAX_BDE)) { rval = emlxs_sli2_fct_bde_setup(port, sbp); } else { rval = emlxs_sli3_fct_bde_setup(port, sbp); @@ -4042,7 +4078,7 @@ emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) uint32_t rval; emlxs_hba_t *hba = HBA; - if (hba->sli_mode < 3) { + if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) { rval = emlxs_sli2_bde_setup(port, sbp); } else { rval = emlxs_sli3_bde_setup(port, sbp); @@ -4237,7 +4273,7 @@ emlxs_sli3_intx_intr(char *arg) /* EMLXS_PORT_LOCK must be held when call this routine */ static uint32_t -emlxs_get_attention(emlxs_hba_t *hba, uint32_t msgid) +emlxs_get_attention(emlxs_hba_t *hba, int32_t msgid) { #ifdef FMA_SUPPORT emlxs_port_t *port = &PPORT; @@ -4550,8 +4586,8 @@ emlxs_sli3_handle_link_event(emlxs_hba_t *hba) rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbq); } mutex_enter(&EMLXS_PORT_LOCK); @@ -4569,7 +4605,7 @@ emlxs_sli3_handle_link_event(emlxs_hba_t *hba) mutex_exit(&EMLXS_PORT_LOCK); } else { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } } @@ -5141,7 +5177,7 @@ done: emlxs_update_HBQ_index(hba, hbq_id); } else { if (mp) { - (void) emlxs_mem_put(hba, buf_type, (uint8_t *)mp); + emlxs_mem_put(hba, buf_type, (void *)mp); } (void) emlxs_post_buffer(hba, rp, 1); } @@ -5223,7 +5259,7 @@ emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) /* Free the local iocb if there is no sbp tracking it */ if (!sbp) { - (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); } /* update local ring index to next available ring index */ @@ -5304,7 +5340,7 @@ mode_A: interlock_A: - value = 0xFFFFFFFF; + value = 0x55555555; word0 = 0; swpmb->mbxCommand = MBX_KILL_BOARD; swpmb->mbxOwner = OWN_CHIP; @@ -5336,14 +5372,14 @@ interlock_A: while (j++ < 1000) { value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); - if (value == 0) { + if (value == 0xAAAAAAAA) { break; } DELAYUS(50); } - if (value == 0) { + if (value == 0xAAAAAAAA) { /* Now wait for mailbox ownership to clear */ while (j++ < 10000) { word0 = @@ -5374,7 +5410,7 @@ mode_B: interlock_B: - value = 0xFFFFFFFF; + value = 0x55555555; word0 = 0; swpmb->mbxCommand = MBX_KILL_BOARD; swpmb->mbxOwner = OWN_CHIP; @@ -5391,14 +5427,14 @@ interlock_B: while (j++ < 1000) { value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); - if (value == 0) { + if (value == 0xAAAAAAAA) { break; } DELAYUS(50); } - if (value == 0) { + if (value == 0xAAAAAAAA) { /* Now wait for mailbox ownership to clear */ while (j++ < 10000) { word0 = @@ -5493,7 +5529,7 @@ emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba) mb1 = FC_SLIM1_MAILBOX(hba); swpmb = (MAILBOX *)&word0; - value = 0xFFFFFFFF; + value = 0x55555555; word0 = 0; swpmb->mbxCommand = MBX_KILL_BOARD; swpmb->mbxOwner = OWN_CHIP; @@ -5525,12 +5561,12 @@ emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba) while (j++ < 1000) { value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); - if (value == 0) { + if (value == 0xAAAAAAAA) { break; } DELAYUS(50); } - if (value == 0) { + if (value == 0xAAAAAAAA) { /* Now wait for mailbox ownership to clear */ while (j++ < 10000) { word0 = @@ -5556,102 +5592,6 @@ done: } /* emlxs_sli3_hba_kill4quiesce */ -static uint32_t -emlxs_reset_ring(emlxs_hba_t *hba, uint32_t ringno) -{ - emlxs_port_t *port = &PPORT; - RING *rp; - MAILBOXQ *mbq; - MAILBOX *mb; - PGP *pgp; - off_t offset; - NODELIST *ndlp; - uint32_t i; - emlxs_port_t *vport; - - rp = &hba->sli.sli3.ring[ringno]; - pgp = - (PGP *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[ringno]; - - if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, - "%s: Unable to allocate mailbox buffer.", - emlxs_ring_xlate(ringno)); - - return ((uint32_t)FC_FAILURE); - } - mb = (MAILBOX *)mbq; - - emlxs_mb_reset_ring(hba, mbq, ringno); - if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, - "%s: Unable to reset ring. Mailbox cmd=%x status=%x", - emlxs_ring_xlate(ringno), mb->mbxCommand, mb->mbxStatus); - - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - return ((uint32_t)FC_FAILURE); - } - - /* Free the mailbox */ - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - - /* Update the response ring indicies */ - offset = (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) - - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); - EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, - DDI_DMA_SYNC_FORKERNEL); - rp->fc_rspidx = rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx); - - /* Update the command ring indicies */ - offset = (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) - - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); - EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, - DDI_DMA_SYNC_FORKERNEL); - rp->fc_cmdidx = rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); - - for (i = 0; i < MAX_VPORTS; i++) { - vport = &VPORT(i); - - if (!(vport->flag & EMLXS_PORT_BOUND)) { - continue; - } - - /* Clear all node XRI contexts */ - rw_enter(&vport->node_rwlock, RW_WRITER); - mutex_enter(&EMLXS_TX_CHANNEL_LOCK); - for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { - ndlp = vport->node_table[i]; - while (ndlp != NULL) { - ndlp->nlp_flag[FC_IP_RING] &= ~NLP_RPI_XRI; - ndlp = ndlp->nlp_list_next; - } - } - mutex_exit(&EMLXS_TX_CHANNEL_LOCK); - rw_exit(&vport->node_rwlock); - } - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, "%s", - emlxs_ring_xlate(ringno)); - -#ifdef FMA_SUPPORT - if (emlxs_fm_check_dma_handle(hba, hba->sli.sli3.slim2.dma_handle) - != DDI_FM_OK) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_invalid_dma_handle_msg, - "emlxs_reset_ring: hdl=%p", - hba->sli.sli3.slim2.dma_handle); - - emlxs_thread_spawn(hba, emlxs_restart_thread, - NULL, NULL); - - return ((uint32_t)FC_FAILURE); - } -#endif /* FMA_SUPPORT */ - - - return (FC_SUCCESS); - -} /* emlxs_reset_ring() */ /* @@ -5670,7 +5610,7 @@ emlxs_handle_mb_event(emlxs_hba_t *hba) MAILBOX *mb; MAILBOX *swpmb; MAILBOX *mbox; - MAILBOXQ *mbq; + MAILBOXQ *mbq = NULL; volatile uint32_t word0; MATCHMAP *mbox_bp; off_t offset; @@ -5679,10 +5619,13 @@ emlxs_handle_mb_event(emlxs_hba_t *hba) swpmb = (MAILBOX *)&word0; + mutex_enter(&EMLXS_PORT_LOCK); switch (hba->mbox_queue_flag) { case 0: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, "No mailbox active."); + + mutex_exit(&EMLXS_PORT_LOCK); return (0); case MBX_POLL: @@ -5695,29 +5638,51 @@ emlxs_handle_mb_event(emlxs_hba_t *hba) mutex_enter(&EMLXS_MBOX_LOCK); mbq = (MAILBOXQ *)hba->mbox_mbq; - mutex_exit(&EMLXS_MBOX_LOCK); if (mbq) { + port = (emlxs_port_t *)mbq->port; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, "Mailbox event. Completing Polled command."); mbq->flag |= MBQ_COMPLETED; } + mutex_exit(&EMLXS_MBOX_LOCK); + mutex_exit(&EMLXS_PORT_LOCK); return (0); case MBX_SLEEP: case MBX_NOWAIT: - mutex_enter(&EMLXS_MBOX_LOCK); - mbq = (MAILBOXQ *)hba->mbox_mbq; + /* Check mbox_timer, it acts as a service flag too */ + /* The first to service the mbox queue will clear the timer */ + if (hba->mbox_timer) { + hba->mbox_timer = 0; + + mutex_enter(&EMLXS_MBOX_LOCK); + mbq = (MAILBOXQ *)hba->mbox_mbq; + mutex_exit(&EMLXS_MBOX_LOCK); + } + + if (!mbq) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, + "Mailbox event. No service required."); + mutex_exit(&EMLXS_PORT_LOCK); + return (0); + } + mb = (MAILBOX *)mbq; - mutex_exit(&EMLXS_MBOX_LOCK); + mutex_exit(&EMLXS_PORT_LOCK); break; default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, "Invalid Mailbox flag (%x)."); + + mutex_exit(&EMLXS_PORT_LOCK); return (0); } + /* Set port context */ + port = (emlxs_port_t *)mbq->port; + /* Get first word of mailbox */ if (hba->flag & FC_SLIM2_MODE) { mbox = FC_SLIM2_MAILBOX(hba); @@ -5754,7 +5719,7 @@ emlxs_handle_mb_event(emlxs_hba_t *hba) word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); } - } + } /* Now that we are the owner, DMA Sync entire mailbox if needed */ if (hba->flag & FC_SLIM2_MODE) { @@ -5855,7 +5820,7 @@ done: /* Attempt to send pending mailboxes */ rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } } return (0); @@ -5894,12 +5859,12 @@ emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba) mutex_exit(&EMLXS_PORT_LOCK); return; } - hba->mbox_timer = 0; /* Mailbox timed out, first check for error attention */ ha_copy = emlxs_check_attention(hba); if (ha_copy & HA_ERATT) { + hba->mbox_timer = 0; mutex_exit(&EMLXS_PORT_LOCK); emlxs_handle_ff_error(hba); return; @@ -5948,9 +5913,13 @@ emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba) return; } - if (hba->mbox_mbq) { - mb = (MAILBOX *)hba->mbox_mbq; - } + /* The first to service the mbox queue will clear the timer */ + /* We will service the mailbox here */ + hba->mbox_timer = 0; + + mutex_enter(&EMLXS_MBOX_LOCK); + mb = (MAILBOX *)hba->mbox_mbq; + mutex_exit(&EMLXS_MBOX_LOCK); } if (mb) { @@ -6285,7 +6254,7 @@ emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) if (emlxs_hbq_alloc(hba, hbq_id)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, "emlxs_hbq_setup: Unable to allocate HBQ."); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); return (1); } @@ -6341,7 +6310,7 @@ emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) "emlxs_hbq_setup: Unable to config HBQ. cmd=%x status=%x", mb->mbxCommand, mb->mbxStatus); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); emlxs_hbq_free_all(hba, hbq_id); return (1); } @@ -6353,7 +6322,7 @@ emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) hba->sli.sli3.hbq_count++; - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); #ifdef FMA_SUPPORT /* Access handle validation */ @@ -6412,8 +6381,8 @@ emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id) if (hbq->HBQ_host_buf.virt != 0) { for (j = 0; j < hbq->HBQ_PostBufCnt; j++) { - (void) emlxs_mem_put(hba, seg, - (uint8_t *)hbq->HBQ_PostBufs[j]); + emlxs_mem_put(hba, seg, + (void *)hbq->HBQ_PostBufs[j]); hbq->HBQ_PostBufs[j] = NULL; } hbq->HBQ_PostBufCnt = 0; diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c index 22243d4608..aefa0996f9 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c @@ -36,11 +36,8 @@ static int emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq); static int emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq); -static int emlxs_fcf_bind(emlxs_hba_t *hba); -static int emlxs_fcf_unbind(emlxs_hba_t *hba, uint32_t index); - -static int emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq); +static int emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq); extern void emlxs_parse_prog_types(emlxs_hba_t *hba, char *types); @@ -71,10 +68,10 @@ static uint32_t emlxs_sli4_hba_init(emlxs_hba_t *hba); static uint32_t emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); -static uint32_t emlxs_sli4_fct_bde_setup(emlxs_port_t *port, - emlxs_buf_t *sbp); + + static void emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, - CHANNEL *rp, IOCBQ *iocb_cmd); + CHANNEL *cp, IOCBQ *iocb_cmd); static uint32_t emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flg, uint32_t tmo); static uint32_t emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, @@ -104,12 +101,8 @@ static void emlxs_sli4_resource_free(emlxs_hba_t *hba); static int emlxs_sli4_resource_alloc(emlxs_hba_t *hba); -static void emlxs_sli4_destroy_queues(emlxs_hba_t *hba); - static XRIobj_t *emlxs_sli4_alloc_xri(emlxs_hba_t *hba, - emlxs_buf_t *sbp, RPIobj_t *rp); -static void emlxs_sli4_free_vpi(emlxs_hba_t *hba, emlxs_port_t *pp); - + emlxs_buf_t *sbp, RPIobj_t *rpip); static void emlxs_sli4_enable_intr(emlxs_hba_t *hba); static void emlxs_sli4_disable_intr(emlxs_hba_t *hba, uint32_t att); @@ -118,15 +111,16 @@ extern void emlxs_sli4_timer(emlxs_hba_t *hba); static void emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba); -extern void emlxs_sli4_poll_erratt(emlxs_hba_t *hba); +static void emlxs_sli4_poll_erratt(emlxs_hba_t *hba); static XRIobj_t *emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri); -static XRIobj_t *emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp); - +static XRIobj_t *emlxs_sli4_reserve_xri(emlxs_hba_t *hba, + RPIobj_t *rpip); static int emlxs_check_hdw_ready(emlxs_hba_t *); + /* Define SLI4 API functions */ emlxs_sli_api_t emlxs_sli4_api = { emlxs_sli4_map_hdw, @@ -183,6 +177,7 @@ emlxs_sli4_online(emlxs_hba_t *hba) uint32_t kern_update = 0; emlxs_firmware_t hba_fw; emlxs_firmware_t *fw; + uint16_t ssvid; cfg = &CFG; vpd = &VPD; @@ -323,7 +318,7 @@ reset: } -emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "RD_REV", (uint32_t *)mb, 18, 0); if (mb->un.varRdRev4.sliLevel != 4) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "Invalid read rev Version for SLI4: 0x%x", @@ -374,8 +369,10 @@ emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); emlxs_decode_label(vpd->opFwName, vpd->opFwName, 0); emlxs_decode_label(vpd->postKernName, vpd->postKernName, 0); - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if (hba->model_info.chip == EMLXS_BE2_CHIP) { (void) strcpy(vpd->sli4FwLabel, "be2.ufi"); + } else if (hba->model_info.chip == EMLXS_BE3_CHIP) { + (void) strcpy(vpd->sli4FwLabel, "be3.ufi"); } else { (void) strcpy(vpd->sli4FwLabel, "sli4.fw"); } @@ -479,6 +476,18 @@ emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); } } + /* HP CNA port indices start at 1 instead of 0 */ + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { + + ssvid = ddi_get16(hba->pci_acc_handle, + (uint16_t *)(hba->pci_addr + PCI_SSVID_REGISTER)); + + if ((ssvid == PCI_SSVID_HP) && (vpd->port_index > 0)) { + vpd->port_index--; + } + } + /* * Now lets update hba->model_info with the real * VPD data, if any. @@ -561,7 +570,8 @@ emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); if (fw) { /* Obtain current firmware version info */ - if (hba->model_info.chip == EMLXS_BE_CHIP) { + if ((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) { (void) emlxs_sli4_read_fw_version(hba, &hba_fw); } else { hba_fw.kern = vpd->postKernRev; @@ -673,7 +683,7 @@ emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); rval = EIO; goto failed1; } -emlxs_data_dump(hba, "REQ_FEATURE", (uint32_t *)mb, 6, 0); +emlxs_data_dump(port, "REQ_FEATURE", (uint32_t *)mb, 6, 0); /* Make sure we get the features we requested */ if (mb->un.varReqFeatures.featuresRequested != @@ -709,7 +719,7 @@ emlxs_data_dump(hba, "REQ_FEATURE", (uint32_t *)mb, 6, 0); rval = EIO; goto failed1; } -emlxs_data_dump(hba, "READ_CONFIG4", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "READ_CONFIG4", (uint32_t *)mb, 18, 0); hba->sli.sli4.XRICount = (mb->un.varRdConfig4.XRICount); hba->sli.sli4.XRIBase = (mb->un.varRdConfig4.XRIBase); @@ -740,7 +750,7 @@ emlxs_data_dump(hba, "READ_CONFIG4", (uint32_t *)mb, 18, 0); hba->max_iotag = hba->sli.sli4.XRICount; /* Save the link speed capabilities */ - vpd->link_speed = mb->un.varRdConfig4.lmt; + vpd->link_speed = (uint16_t)mb->un.varRdConfig4.lmt; emlxs_process_link_speed(hba); /* @@ -767,7 +777,7 @@ emlxs_data_dump(hba, "READ_CONFIG4", (uint32_t *)mb, 18, 0); rval = ENOMEM; goto failed2; } -emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); +emlxs_data_dump(port, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); #if (EMLXS_MODREV >= EMLXS_MODREV5) if ((cfg[CFG_NPIV_ENABLE].current) && (hba->flag & FC_NPIV_ENABLED)) { @@ -837,7 +847,7 @@ emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); * We need to get login parameters for NID */ (void) emlxs_mb_read_sparam(hba, mbq); - mp = (MATCHMAP *)(mbq->bp); + mp = (MATCHMAP *)mbq->bp; if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, "Unable to read parameters. Mailbox cmd=%x status=%x", @@ -848,7 +858,7 @@ emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); } /* Free the buffer since we were polling */ - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); mp = NULL; /* If no serial number in VPD data, then use the WWPN */ @@ -887,7 +897,7 @@ emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); } /* Make attempt to set a port index */ - if (vpd->port_index == -1) { + if (vpd->port_index == (uint32_t)-1) { dev_info_t *p_dip; dev_info_t *c_dip; @@ -967,7 +977,7 @@ emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to initialize link. " \ + "Unable to initialize link. " "Mailbox cmd=%x status=%x", mb->mbxCommand, mb->mbxStatus); @@ -992,6 +1002,8 @@ emlxs_data_dump(hba, "XRIp", (uint32_t *)hba->sli.sli4.XRIp, 18, 0); DELAYMS(1000); i--; } + } else { + EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST); } /* @@ -1009,7 +1021,7 @@ failed3: EMLXS_STATE_CHANGE(hba, FC_ERROR); if (mp) { - (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); + emlxs_mem_put(hba, MEM_BUF, (void *)mp); mp = NULL; } @@ -1146,7 +1158,7 @@ emlxs_sli4_map_hdw(emlxs_hba_t *hba) goto failed; } - hba->sli.sli4.bootstrapmb.virt = (uint8_t *)buf_info->virt; + hba->sli.sli4.bootstrapmb.virt = buf_info->virt; hba->sli.sli4.bootstrapmb.phys = buf_info->phys; hba->sli.sli4.bootstrapmb.size = EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE; @@ -1214,11 +1226,11 @@ emlxs_sli4_unmap_hdw(emlxs_hba_t *hba) buf_info->flags = FC_MBUF_DMA; } - buf_info->virt = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; + buf_info->virt = hba->sli.sli4.bootstrapmb.virt; buf_info->size = hba->sli.sli4.bootstrapmb.size; emlxs_mem_free(hba, buf_info); - hba->sli.sli4.bootstrapmb.virt = 0; + hba->sli.sli4.bootstrapmb.virt = NULL; } return; @@ -1404,13 +1416,13 @@ emlxs_init_bootstrap_mb(emlxs_hba_t *hba) EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); -emlxs_data_dump(hba, "EndianIN", (uint32_t *)iptr, 6, 0); +emlxs_data_dump(port, "EndianIN", (uint32_t *)iptr, 6, 0); if (!emlxs_issue_bootstrap_mb(hba, tmo)) { return (1); } EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); -emlxs_data_dump(hba, "EndianOUT", (uint32_t *)iptr, 6, 0); +emlxs_data_dump(port, "EndianOUT", (uint32_t *)iptr, 6, 0); #ifdef FMA_SUPPORT if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle) @@ -1432,7 +1444,7 @@ static uint32_t emlxs_sli4_hba_init(emlxs_hba_t *hba) { int rc; - uint32_t i; + uint16_t i; emlxs_port_t *vport; emlxs_config_t *cfg = &CFG; CHANNEL *cp; @@ -1454,6 +1466,10 @@ emlxs_sli4_hba_init(emlxs_hba_t *hba) vport = &VPORT(i); vport->hba = hba; vport->vpi = i; + + vport->VPIobj.index = i; + vport->VPIobj.VPI = i; + vport->VPIobj.port = vport; } /* Set the max node count */ @@ -1497,7 +1513,7 @@ emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, MAILBOXQ mboxq; uint32_t i; uint32_t rc; - uint32_t channelno; + uint16_t channelno; if (!cfg[CFG_RESET_ENABLE].current) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, @@ -1541,7 +1557,7 @@ emlxs_sli4_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, return (1); } } -emlxs_data_dump(hba, "resetPort", (uint32_t *)&mboxq, 12, 0); +emlxs_data_dump(port, "resetPort", (uint32_t *)&mboxq, 12, 0); /* Reset the hba structure */ hba->flag &= FC_RESET_MASK; @@ -1571,6 +1587,7 @@ emlxs_data_dump(hba, "resetPort", (uint32_t *)&mboxq, 12, 0); vport->prev_did = 0; vport->lip_type = 0; bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); + bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM)); bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); vport->node_base.nlp_Rpi = 0; @@ -1672,7 +1689,6 @@ emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt, cnt = 0; for (i = 0; i < cookie_cnt && size > 0; i++, cp++) { - sge_size = cp->dmac_size; sge_addr = cp->dmac_laddress; while (sge_size && size) { @@ -1694,7 +1710,7 @@ emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt, stage_sge.offset = cnt; } #ifdef DEBUG_SGE - emlxs_data_dump(hba, "SGE", (uint32_t *)&stage_sge, + emlxs_data_dump(port, "SGE", (uint32_t *)&stage_sge, 4, 0); #endif sge_addr += len; @@ -1710,6 +1726,7 @@ emlxs_pkt_to_sgl(emlxs_port_t *port, ULP_SGE64 *sge, fc_packet_t *pkt, } BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, sizeof (ULP_SGE64)); + sge++; *pcnt = cnt; @@ -1723,7 +1740,7 @@ uint32_t emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) { fc_packet_t *pkt; - XRIobj_t *xp; + XRIobj_t *xrip; ULP_SGE64 *sge; emlxs_wqe_t *wqe; IOCBQ *iocbq; @@ -1735,8 +1752,8 @@ emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) iocbq = (IOCBQ *) &sbp->iocbq; wqe = &iocbq->wqe; pkt = PRIV2PKT(sbp); - xp = sbp->xp; - sge = xp->SGList.virt; + xrip = sbp->xrip; + sge = xrip->SGList.virt; #if (EMLXS_MODREV >= EMLXS_MODREV3) cp_cmd = pkt->pkt_cmd_cookie; @@ -1803,13 +1820,6 @@ emlxs_sli4_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) } /* emlxs_sli4_bde_setup */ -/*ARGSUSED*/ -static uint32_t -emlxs_sli4_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) -{ - return (0); - -} /* emlxs_sli4_fct_bde_setup */ static void @@ -1824,7 +1834,7 @@ emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) WQ_DESC_t *wq; uint32_t flag; uint32_t wqdb; - uint32_t next_wqe; + uint16_t next_wqe; off_t offset; @@ -1849,7 +1859,7 @@ emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) } /* Attempt to acquire CMD_RING lock */ - if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) { + if (mutex_tryenter(&EMLXS_QUE_LOCK(channelno)) == 0) { /* Queue it for later */ if (iocbq) { if ((hba->io_count - @@ -1858,13 +1868,13 @@ emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) return; } else { - mutex_enter(&EMLXS_CMD_RING_LOCK(channelno)); + mutex_enter(&EMLXS_QUE_LOCK(channelno)); } } else { return; } } - /* CMD_RING_LOCK acquired */ + /* EMLXS_QUE_LOCK acquired */ /* Throttle check only applies to non special iocb */ if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) { @@ -1933,7 +1943,7 @@ sendit: sbp = iocbq->sbp; if (sbp) { /* If exchange removed after wqe was prep'ed, drop it */ - if (!(sbp->xp)) { + if (!(sbp->xrip)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "Xmit WQE iotag: %x xri: %x aborted", wqe->RequestTag, wqe->XRITag); @@ -1982,7 +1992,7 @@ sendit: mutex_exit(&sbp->mtx); atomic_add_32(&hba->io_active, 1); - sbp->xp->state |= RESOURCE_XRI_PENDING_IO; + sbp->xrip->flag |= EMLXS_XRI_PENDING_IO; } @@ -2014,7 +2024,7 @@ sendit: BE_SWAP32_BCOPY((uint8_t *)wqe, (uint8_t *)wqeslot, sizeof (emlxs_wqe_t)); #ifdef DEBUG_WQE - emlxs_data_dump(hba, "WQE", (uint32_t *)wqe, 18, 0); + emlxs_data_dump(port, "WQE", (uint32_t *)wqe, 18, 0); #endif offset = (off_t)((uint64_t)((unsigned long) wq->addr.virt) - @@ -2043,7 +2053,7 @@ sendit: */ if (!sbp) { - (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); } if (iocbq && (!(flag & IOCB_SPECIAL))) { @@ -2070,7 +2080,7 @@ sendit: iocbq = emlxs_tx_get(cp, 1); } - mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); + mutex_exit(&EMLXS_QUE_LOCK(channelno)); return; @@ -2081,7 +2091,7 @@ busy: HBASTATS.IocbRingFull[channelno]++; } - mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); + mutex_exit(&EMLXS_QUE_LOCK(channelno)); return; @@ -2090,9 +2100,10 @@ busy: /*ARGSUSED*/ static uint32_t -emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) +emlxs_sli4_issue_mq(emlxs_port_t *port, MAILBOX4 *mqe, MAILBOX *mb, + uint32_t tmo) { - emlxs_port_t *port = &PPORT; + emlxs_hba_t *hba = HBA; MAILBOXQ *mbq; MAILBOX4 *mb4; MATCHMAP *mp; @@ -2103,7 +2114,7 @@ emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) mbq = (MAILBOXQ *)mb; mb4 = (MAILBOX4 *)mb; mp = (MATCHMAP *) mbq->nonembed; - hba->mbox_mqe = (uint32_t *)mqe; + hba->mbox_mqe = (void *)mqe; if ((mb->mbxCommand != MBX_SLI_CONFIG) || (mb4->un.varSLIConfig.be.embedded)) { @@ -2117,7 +2128,10 @@ emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0, 4096, DDI_DMA_SYNC_FORDEV); - emlxs_data_dump(hba, "MBOX CMD", (uint32_t *)mqe, 18, 0); + if (mb->mbxCommand != MBX_HEARTBEAT) { + emlxs_data_dump(port, "MBOX CMD", (uint32_t *)mqe, + 18, 0); + } } else { /* SLI_CONFIG and non-embedded */ @@ -2151,18 +2165,20 @@ emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORDEV); - emlxs_data_dump(hba, "MBOX EXT", (uint32_t *)mqe, 12, 0); + emlxs_data_dump(port, "MBOX EXT", (uint32_t *)mqe, 12, 0); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, "Extension Addr %p %p", mp->phys, (uint32_t *)(mp->virt)); - emlxs_data_dump(hba, "EXT AREA", (uint32_t *)mp->virt, 24, 0); + emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0); } /* Ring the MQ Doorbell */ mqdb = hba->sli.sli4.mq.qid; mqdb |= ((1 << MQ_DB_POP_SHIFT) & MQ_DB_POP_MASK); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "MQ RING: %08x", mqdb); + if (mb->mbxCommand != MBX_HEARTBEAT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "MQ RING: %08x", mqdb); + } WRITE_BAR2_REG(hba, FC_MQDB_REG(hba), mqdb); return (MBX_SUCCESS); @@ -2184,7 +2200,7 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) mbq = (MAILBOXQ *)mb; mb4 = (MAILBOX4 *)mb; mp = (MATCHMAP *) mbq->nonembed; - hba->mbox_mqe = (uint32_t *)hba->sli.sli4.bootstrapmb.virt; + hba->mbox_mqe = hba->sli.sli4.bootstrapmb.virt; if ((mb->mbxCommand != MBX_SLI_CONFIG) || (mb4->un.varSLIConfig.be.embedded)) { @@ -2198,7 +2214,7 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, MAILBOX_CMD_SLI4_BSIZE, DDI_DMA_SYNC_FORDEV); - emlxs_data_dump(hba, "MBOX CMD", iptr, 18, 0); + emlxs_data_dump(port, "MBOX CMD", iptr, 18, 0); } else { /* * If this is not embedded, the bootstrap mailbox area @@ -2228,12 +2244,12 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) EMLXS_BOOTSTRAP_MB_SIZE + MBOX_EXTENSION_SIZE, DDI_DMA_SYNC_FORDEV); - emlxs_data_dump(hba, "MBOX EXT", iptr, 12, 0); + emlxs_data_dump(port, "MBOX EXT", iptr, 12, 0); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, "Extension Addr %p %p", mp->phys, (uint32_t *)((uint8_t *)mp->virt)); iptr = (uint32_t *)((uint8_t *)mp->virt); - emlxs_data_dump(hba, "EXT AREA", (uint32_t *)mp->virt, 24, 0); + emlxs_data_dump(port, "EXT AREA", (uint32_t *)mp->virt, 24, 0); } @@ -2251,7 +2267,7 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb, MAILBOX_CMD_SLI4_BSIZE); - emlxs_data_dump(hba, "MBOX CMPL", iptr, 18, 0); + emlxs_data_dump(port, "MBOX CMP", iptr, 18, 0); } else { EMLXS_MPDATA_SYNC(hba->sli.sli4.bootstrapmb.dma_handle, 0, @@ -2267,9 +2283,9 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)mb, MAILBOX_CMD_SLI4_BSIZE); - emlxs_data_dump(hba, "MBOX CMPL", iptr, 12, 0); + emlxs_data_dump(port, "MBOX CMP", iptr, 12, 0); iptr = (uint32_t *)((uint8_t *)mp->virt); - emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0); + emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0); } #ifdef FMA_SUPPORT @@ -2305,7 +2321,7 @@ static uint32_t emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, uint32_t tmo) { - emlxs_port_t *port = &PPORT; + emlxs_port_t *port; MAILBOX4 *mb4; MAILBOX *mb; mbox_rsp_hdr_t *hdr_rsp; @@ -2315,6 +2331,12 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, uint32_t i; uint32_t tmo_local; + if (!mbq->port) { + mbq->port = &PPORT; + } + + port = (emlxs_port_t *)mbq->port; + mb4 = (MAILBOX4 *)mbq; mb = (MAILBOX *)mbq; @@ -2364,7 +2386,7 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, mutex_exit(&EMLXS_PORT_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, - "Mailbox Queue missing %s failed", + "Interrupts disabled. %s failed.", emlxs_mb_cmd_xlate(mb->mbxCommand)); return (MBX_HARDWARE_ERROR); @@ -2427,6 +2449,10 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, /* Initialize mailbox area */ emlxs_mb_init(hba, mbq, flag, tmo); + if (mb->mbxCommand == MBX_DOWN_LINK) { + hba->sli.sli4.flag |= EMLXS_SLI4_DOWN_LINK; + } + mutex_exit(&EMLXS_PORT_LOCK); switch (flag) { @@ -2456,10 +2482,10 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, ((MATCHMAP *)mbq->bp)->virt, ((MATCHMAP *)mbq->bp)->phys, ((MATCHMAP *)mbq->bp)->size); - emlxs_data_dump(hba, "DATA", + emlxs_data_dump(port, "DATA", (uint32_t *)(((MATCHMAP *)mbq->bp)->virt), 30, 0); } - rc = emlxs_sli4_issue_mq(hba, (MAILBOX4 *)iptr, mb, tmo_local); + rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local); break; case MBX_POLL: @@ -2491,7 +2517,7 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, - "Completed. %s: mb=%p status=%x Poll. " \ + "Completed. %s: mb=%p status=%x Poll. " "embedded %d", emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc, ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : @@ -2512,6 +2538,12 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, if (mp) { hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; if (hdr_rsp->status) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_mbox_detail_msg, + "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", + emlxs_mb_cmd_xlate(mb->mbxCommand), + hdr_rsp->status, hdr_rsp->extra_status); + mb->mbxStatus = MBX_NONEMBED_ERROR; } } @@ -2523,8 +2555,7 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, /* Attempt to send pending mailboxes */ i = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); if ((i != MBX_BUSY) && (i != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } } break; @@ -2546,7 +2577,7 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, hba->sli.sli4.mq.host_index = 0; } - rc = emlxs_sli4_issue_mq(hba, (MAILBOX4 *)iptr, mb, tmo_local); + rc = emlxs_sli4_issue_mq(port, (MAILBOX4 *)iptr, mb, tmo_local); if (rc != MBX_SUCCESS) { break; @@ -2565,6 +2596,12 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, if (mp) { hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; if (hdr_rsp->status) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_mbox_detail_msg, + "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", + emlxs_mb_cmd_xlate(mb->mbxCommand), + hdr_rsp->status, hdr_rsp->extra_status); + mb->mbxStatus = MBX_NONEMBED_ERROR; } } @@ -2581,7 +2618,7 @@ emlxs_sli4_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, /* && mb->mbxCommand != MBX_DUMP_MEMORY */) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, - "Completed. %s: mb=%p status=%x Sleep. " \ + "Completed. %s: mb=%p status=%x Sleep. " "embedded %d", emlxs_mb_cmd_xlate(mb->mbxCommand), mb, rc, ((mb->mbxCommand != MBX_SLI_CONFIG) ? 1 : @@ -2659,6 +2696,12 @@ emlxs_sli4_issue_mbox_cmd4quiesce(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, if (mp) { hdr_rsp = (mbox_rsp_hdr_t *)mp->virt; if (hdr_rsp->status) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_mbox_detail_msg, + "%s: MBX_NONEMBED_ERROR: 0x%x, 0x%x", + emlxs_mb_cmd_xlate(mb->mbxCommand), + hdr_rsp->status, hdr_rsp->extra_status); + mb->mbxStatus = MBX_NONEMBED_ERROR; } } @@ -2691,8 +2734,8 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) emlxs_hba_t *hba = HBA; fc_packet_t *pkt; CHANNEL *cp; - RPIobj_t *rp; - XRIobj_t *xp; + RPIobj_t *rpip; + XRIobj_t *xrip; emlxs_wqe_t *wqe; IOCBQ *iocbq; NODELIST *node; @@ -2713,9 +2756,9 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) /* Find target node object */ node = (NODELIST *)iocbq->node; - rp = EMLXS_NODE_TO_RPI(hba, node); + rpip = EMLXS_NODE_TO_RPI(port, node); - if (!rp) { + if (!rpip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, "Unable to find rpi. did=0x%x", did); @@ -2726,9 +2769,9 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) sbp->channel = cp; /* Next allocate an Exchange for this command */ - xp = emlxs_sli4_alloc_xri(hba, sbp, rp); + xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, "Adapter Busy. Unable to allocate exchange. did=0x%x", did); @@ -2739,14 +2782,14 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) #ifdef SLI4_FASTPATH_DEBUG EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, /* DEBUG */ - "Prep FCP iotag: %x xri: %x", iotag, xp->XRI); + "Prep FCP iotag: %x xri: %x", iotag, xrip->XRI); #endif /* Indicate this is a FCP cmd */ iocbq->flag |= IOCB_FCP_CMD; if (emlxs_sli4_bde_setup(port, sbp)) { - emlxs_sli4_free_xri(hba, sbp, xp); + emlxs_sli4_free_xri(hba, sbp, xrip, 1); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, "Adapter Busy. Unable to setup SGE. did=0x%x", did); @@ -2757,22 +2800,22 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) /* DEBUG */ #ifdef DEBUG_FCP EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "SGLaddr virt %p phys %p size %d", xp->SGList.virt, - xp->SGList.phys, pkt->pkt_datalen); - emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 20, 0); + "SGLaddr virt %p phys %p size %d", xrip->SGList.virt, + xrip->SGList.phys, pkt->pkt_datalen); + emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt, 20, 0); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CMD virt %p len %d:%d:%d", pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen, pkt->pkt_datalen); - emlxs_data_dump(hba, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0); + emlxs_data_dump(port, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0); #endif offset = (off_t)((uint64_t)((unsigned long) - xp->SGList.virt) - + xrip->SGList.virt) - (uint64_t)((unsigned long) hba->sli.sli4.slim2.virt)); - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, offset, - xp->SGList.size, DDI_DMA_SYNC_FORDEV); + EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset, + xrip->SGList.size, DDI_DMA_SYNC_FORDEV); /* if device is FCP-2 device, set the following bit */ /* that says to run the FC-TAPE protocol. */ @@ -2793,9 +2836,9 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) } wqe->un.FcpCmd.TotalTransferCount = pkt->pkt_datalen; - wqe->ContextTag = rp->RPI; + wqe->ContextTag = rpip->RPI; wqe->ContextType = WQE_RPI_CONTEXT; - wqe->XRITag = xp->XRI; + wqe->XRITag = xrip->XRI; wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); @@ -2838,9 +2881,9 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) IOCBQ *iocbq; IOCB *iocb; emlxs_wqe_t *wqe; - FCFIobj_t *fp; - RPIobj_t *rp = NULL; - XRIobj_t *xp; + FCFIobj_t *fcfp; + RPIobj_t *rpip = NULL; + XRIobj_t *xrip; CHANNEL *cp; uint32_t did; uint32_t cmd; @@ -2882,14 +2925,16 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) sge->addrLow = PADDR_LO(cp_cmd->dmac_laddress); sge->length = pkt->pkt_cmdlen; sge->offset = 0; + sge->reserved = 0; /* Initalize iocb */ if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { /* ELS Response */ - xp = emlxs_sli4_register_xri(hba, sbp, pkt->pkt_cmd_fhdr.rx_id); + xrip = emlxs_sli4_register_xri(hba, sbp, + pkt->pkt_cmd_fhdr.rx_id); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, "Unable to find XRI. rxid=%x", pkt->pkt_cmd_fhdr.rx_id); @@ -2899,9 +2944,9 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) return (0xff); } - rp = xp->RPIp; + rpip = xrip->rpip; - if (!rp) { + if (!rpip) { /* This means that we had a node registered */ /* when the unsol request came in but the node */ /* has since been unregistered. */ @@ -2916,7 +2961,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "Prep ELS XRI: xri=%x iotag=%x oxid=%x rpi=%x", - xp->XRI, xp->iotag, xp->rx_id, rp->RPI); + xrip->XRI, xrip->iotag, xrip->rx_id, rpip->RPI); wqe->Command = CMD_XMIT_ELS_RSP64_CX; wqe->CmdType = WQE_TYPE_GEN; @@ -2931,39 +2976,39 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) sge->last = 1; /* Now sge is fully staged */ - sge = xp->SGList.virt; + sge = xrip->SGList.virt; BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, sizeof (ULP_SGE64)); - wqe->ContextTag = port->vpi + hba->vpi_base; + wqe->ContextTag = port->VPIobj.VPI; wqe->ContextType = WQE_VPI_CONTEXT; - wqe->OXId = xp->rx_id; + wqe->OXId = xrip->rx_id; } else { /* ELS Request */ node = (emlxs_node_t *)iocbq->node; - rp = EMLXS_NODE_TO_RPI(hba, node); + rpip = EMLXS_NODE_TO_RPI(port, node); + fcfp = port->VPIobj.vfip->fcfp; - if (!rp) { - fp = hba->sli.sli4.FCFIp; - rp = &fp->scratch_rpi; + if (!rpip) { + rpip = port->VPIobj.rpip; } /* Next allocate an Exchange for this command */ - xp = emlxs_sli4_alloc_xri(hba, sbp, rp); + xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "Adapter Busy. Unable to allocate exchange. " \ + "Adapter Busy. Unable to allocate exchange. " "did=0x%x", did); return (FC_TRAN_BUSY); } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Prep ELS XRI: xri=%x iotag=%x rpi=%x", xp->XRI, - xp->iotag, rp->RPI); + "Prep ELS XRI: xri=%x iotag=%x rpi=%x", xrip->XRI, + xrip->iotag, rpip->RPI); wqe->Command = CMD_ELS_REQUEST64_CR; wqe->CmdType = WQE_TYPE_ELS; @@ -2978,7 +3023,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) sge->last = 0; - sge = xp->SGList.virt; + sge = xrip->SGList.virt; BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, sizeof (ULP_SGE64)); @@ -2994,18 +3039,19 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) sge->last = 1; /* Now sge is fully staged */ - sge = xp->SGList.virt; + sge = xrip->SGList.virt; sge++; BE_SWAP32_BCOPY((uint8_t *)&stage_sge, (uint8_t *)sge, sizeof (ULP_SGE64)); #ifdef DEBUG_ELS EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "SGLaddr virt %p phys %p", - xp->SGList.virt, xp->SGList.phys); + xrip->SGList.virt, xrip->SGList.phys); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "PAYLOAD virt %p phys %p", pkt->pkt_cmd, cp_cmd->dmac_laddress); - emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 12, 0); + emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt, + 12, 0); #endif cmd = *((uint32_t *)pkt->pkt_cmd); @@ -3014,7 +3060,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) switch (cmd) { case ELS_CMD_FLOGI: wqe->un.ElsCmd.SP = 1; - wqe->ContextTag = fp->FCFI; + wqe->ContextTag = fcfp->FCFI; wqe->ContextType = WQE_FCFI_CONTEXT; if (hba->flag & FC_FIP_SUPPORTED) { wqe->CmdType |= WQE_TYPE_MASK_FIP; @@ -3023,7 +3069,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) break; case ELS_CMD_FDISC: wqe->un.ElsCmd.SP = 1; - wqe->ContextTag = port->vpi + hba->vpi_base; + wqe->ContextTag = port->VPIobj.VPI; wqe->ContextType = WQE_VPI_CONTEXT; if (hba->flag & FC_FIP_SUPPORTED) { wqe->CmdType |= WQE_TYPE_MASK_FIP; @@ -3031,12 +3077,16 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) } break; case ELS_CMD_LOGO: - wqe->ContextTag = port->vpi + hba->vpi_base; - wqe->ContextType = WQE_VPI_CONTEXT; - if ((hba->flag & FC_FIP_SUPPORTED) && - (did == FABRIC_DID)) { - wqe->CmdType |= WQE_TYPE_MASK_FIP; - wqe->ELSId |= WQE_ELSID_LOGO; + if (did == FABRIC_DID) { + wqe->ContextTag = fcfp->FCFI; + wqe->ContextType = WQE_FCFI_CONTEXT; + if (hba->flag & FC_FIP_SUPPORTED) { + wqe->CmdType |= WQE_TYPE_MASK_FIP; + wqe->ELSId |= WQE_ELSID_LOGO; + } + } else { + wqe->ContextTag = port->VPIobj.VPI; + wqe->ContextType = WQE_VPI_CONTEXT; } break; @@ -3044,7 +3094,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) case ELS_CMD_PLOGI: case ELS_CMD_PRLI: default: - wqe->ContextTag = port->vpi + hba->vpi_base; + wqe->ContextTag = port->VPIobj.VPI; wqe->ContextType = WQE_VPI_CONTEXT; break; } @@ -3053,12 +3103,12 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) } offset = (off_t)((uint64_t)((unsigned long) - xp->SGList.virt) - + xrip->SGList.virt) - (uint64_t)((unsigned long) hba->sli.sli4.slim2.virt)); - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, offset, - xp->SGList.size, DDI_DMA_SYNC_FORDEV); + EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset, + xrip->SGList.size, DDI_DMA_SYNC_FORDEV); if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { wqe->CCPE = 1; @@ -3075,8 +3125,8 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) break; } sbp->class = wqe->Class; - wqe->XRITag = xp->XRI; - wqe->RequestTag = xp->iotag; + wqe->XRITag = xrip->XRI; + wqe->RequestTag = xrip->iotag; wqe->CQId = 0x3ff; return (FC_SUCCESS); @@ -3094,8 +3144,8 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) emlxs_wqe_t *wqe; NODELIST *node = NULL; CHANNEL *cp; - RPIobj_t *rp; - XRIobj_t *xp; + RPIobj_t *rpip; + XRIobj_t *xrip; uint32_t did; off_t offset; @@ -3120,9 +3170,10 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { /* CT Response */ - xp = emlxs_sli4_register_xri(hba, sbp, pkt->pkt_cmd_fhdr.rx_id); + xrip = emlxs_sli4_register_xri(hba, sbp, + pkt->pkt_cmd_fhdr.rx_id); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, "Unable to find XRI. rxid=%x", pkt->pkt_cmd_fhdr.rx_id); @@ -3132,9 +3183,9 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) return (0xff); } - rp = xp->RPIp; + rpip = xrip->rpip; - if (!rp) { + if (!rpip) { /* This means that we had a node registered */ /* when the unsol request came in but the node */ /* has since been unregistered. */ @@ -3148,8 +3199,8 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Prep CT XRI: xri=%x iotag=%x oxid=%x", xp->XRI, - xp->iotag, xp->rx_id); + "Prep CT XRI: xri=%x iotag=%x oxid=%x", xrip->XRI, + xrip->iotag, xrip->rx_id); if (emlxs_sli4_bde_setup(port, sbp)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, @@ -3173,7 +3224,7 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) wqe->un.XmitSeq.DFctl = pkt->pkt_cmd_fhdr.df_ctl; wqe->un.XmitSeq.Rctl = pkt->pkt_cmd_fhdr.r_ctl; wqe->un.XmitSeq.Type = pkt->pkt_cmd_fhdr.type; - wqe->OXId = xp->rx_id; + wqe->OXId = xrip->rx_id; wqe->XC = 0; /* xri_tag is a new exchange */ wqe->CmdSpecific[0] = wqe->un.GenReq.Payload.tus.f.bdeSize; @@ -3181,11 +3232,12 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) /* CT Request */ node = (emlxs_node_t *)iocbq->node; - rp = EMLXS_NODE_TO_RPI(hba, node); + rpip = EMLXS_NODE_TO_RPI(port, node); - if (!rp) { + if (!rpip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, - "Unable to find rpi. did=0x%x", did); + "Unable to find rpi. did=0x%x rpi=%x", + did, node->nlp_Rpi); emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, IOERR_INVALID_RPI, 0); @@ -3193,24 +3245,24 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) } /* Next allocate an Exchange for this command */ - xp = emlxs_sli4_alloc_xri(hba, sbp, rp); + xrip = emlxs_sli4_alloc_xri(hba, sbp, rpip); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "Adapter Busy. Unable to allocate exchange. " \ + "Adapter Busy. Unable to allocate exchange. " "did=0x%x", did); return (FC_TRAN_BUSY); } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Prep CT XRI: %x iotag %x", xp->XRI, xp->iotag); + "Prep CT XRI: %x iotag %x", xrip->XRI, xrip->iotag); if (emlxs_sli4_bde_setup(port, sbp)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, "Adapter Busy. Unable to setup SGE. did=0x%x", did); - emlxs_sli4_free_xri(hba, sbp, xp); + emlxs_sli4_free_xri(hba, sbp, xrip, 1); return (FC_TRAN_BUSY); } @@ -3224,13 +3276,14 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) #ifdef DEBUG_CT EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "SGLaddr virt %p phys %p", xp->SGList.virt, - xp->SGList.phys); - emlxs_data_dump(hba, "SGL", (uint32_t *)xp->SGList.virt, 12, 0); + "SGLaddr virt %p phys %p", xrip->SGList.virt, + xrip->SGList.phys); + emlxs_data_dump(port, "SGL", (uint32_t *)xrip->SGList.virt, + 12, 0); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CMD virt %p len %d:%d", pkt->pkt_cmd, pkt->pkt_cmdlen, pkt->pkt_rsplen); - emlxs_data_dump(hba, "DATA", (uint32_t *)pkt->pkt_cmd, 20, 0); + emlxs_data_dump(port, "DATA", (uint32_t *)pkt->pkt_cmd, 20, 0); #endif /* DEBUG_CT */ } @@ -3241,16 +3294,16 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) iocb->ULPPU = 1; /* Wd4 is relative offset */ offset = (off_t)((uint64_t)((unsigned long) - xp->SGList.virt) - + xrip->SGList.virt) - (uint64_t)((unsigned long) hba->sli.sli4.slim2.virt)); - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, offset, - xp->SGList.size, DDI_DMA_SYNC_FORDEV); + EMLXS_MPDATA_SYNC(xrip->SGList.dma_handle, offset, + xrip->SGList.size, DDI_DMA_SYNC_FORDEV); - wqe->ContextTag = rp->RPI; + wqe->ContextTag = rpip->RPI; wqe->ContextType = WQE_RPI_CONTEXT; - wqe->XRITag = xp->XRI; + wqe->XRITag = xrip->XRI; if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { wqe->CCPE = 1; @@ -3267,7 +3320,7 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) break; } sbp->class = wqe->Class; - wqe->RequestTag = xp->iotag; + wqe->RequestTag = xrip->iotag; wqe->CQId = 0x3ff; return (FC_SUCCESS); @@ -3276,21 +3329,16 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) /*ARGSUSED*/ static int -emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) +emlxs_sli4_read_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) { uint32_t *ptr; - int num_entries = 0; EQE_u eqe; - uint32_t host_index, shost_index; int rc = 0; off_t offset; /* EMLXS_PORT_LOCK must be held when entering this routine */ ptr = eq->addr.virt; ptr += eq->host_index; - host_index = eq->host_index; - - shost_index = host_index; offset = (off_t)((uint64_t)((unsigned long) eq->addr.virt) - @@ -3302,36 +3350,18 @@ emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) mutex_enter(&EMLXS_PORT_LOCK); - for (;;) { - eqe.word = *ptr; - eqe.word = BE_SWAP32(eqe.word); - - if (eqe.word & EQE_VALID) { - rc = 1; - break; - } - - *ptr = 0; - num_entries++; - host_index++; - if (host_index >= eq->max_index) { - host_index = 0; - ptr = eq->addr.virt; - } else { - ptr++; - } + eqe.word = *ptr; + eqe.word = BE_SWAP32(eqe.word); - if (host_index == shost_index) { - /* We donot need to loop forever */ - break; - } + if (eqe.word & EQE_VALID) { + rc = 1; } mutex_exit(&EMLXS_PORT_LOCK); return (rc); -} /* emlxs_sli4_poll_eq */ +} /* emlxs_sli4_read_eq */ /*ARGSUSED*/ @@ -3350,7 +3380,7 @@ emlxs_sli4_poll_intr(emlxs_hba_t *hba, uint32_t att_bit) for (;;) { if (hba->intr_type == DDI_INTR_TYPE_FIXED) { /* only poll eqe0 */ - rc = emlxs_sli4_poll_eq(hba, + rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[0]); if (rc == 1) { (void) bcopy((char *)&arg[0], @@ -3360,7 +3390,7 @@ emlxs_sli4_poll_intr(emlxs_hba_t *hba, uint32_t att_bit) } else { /* poll every msi vector */ for (i = 0; i < hba->intr_count; i++) { - rc = emlxs_sli4_poll_eq(hba, + rc = emlxs_sli4_read_eq(hba, &hba->sli.sli4.eq[i]); if (rc == 1) { @@ -3388,93 +3418,105 @@ static void emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe) { emlxs_port_t *port = &PPORT; - CQE_ASYNC_FCOE_t *fcoe; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CQ ENTRY: process async event %d stat %d tag %d", - cqe->event_code, cqe->link_status, cqe->event_tag); + /* Save the event tag */ + hba->link_event_tag = cqe->un.link.event_tag; - hba->link_event_tag = cqe->event_tag; switch (cqe->event_code) { case ASYNC_EVENT_CODE_LINK_STATE: - switch (cqe->link_status) { + switch (cqe->un.link.link_status) { case ASYNC_EVENT_PHYS_LINK_UP: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Physical link up received"); + "Link Async Event: PHYS_LINK_UP. val=%d type=%x", + cqe->valid, cqe->event_type); break; case ASYNC_EVENT_PHYS_LINK_DOWN: case ASYNC_EVENT_LOGICAL_LINK_DOWN: - if (hba->state > FC_LINK_DOWN) { - (void) emlxs_fcf_unbind(hba, - MAX_FCFCONNECTLIST_ENTRIES); - } - /* Log the link event */ - emlxs_log_link_event(port); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "Link Async Event: LINK_DOWN. val=%d type=%x", + cqe->valid, cqe->event_type); + + (void) emlxs_fcf_linkdown_notify(port); + + mutex_enter(&EMLXS_PORT_LOCK); + hba->sli.sli4.flag &= ~EMLXS_SLI4_DOWN_LINK; + mutex_exit(&EMLXS_PORT_LOCK); break; case ASYNC_EVENT_LOGICAL_LINK_UP: - /* If link not already up then declare it up now */ - if (hba->state < FC_LINK_UP) { - if (cqe->port_speed == PHY_1GHZ_LINK) { - hba->linkspeed = LA_1GHZ_LINK; - } else { - hba->linkspeed = LA_10GHZ_LINK; - } - hba->topology = TOPOLOGY_PT_PT; - hba->qos_linkspeed = cqe->qos_link_speed; + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "Link Async Event: LOGICAL_LINK_UP. val=%d type=%x", + cqe->valid, cqe->event_type); - /* - * This link is not really up till we have - * a valid FCF. - */ - (void) emlxs_fcf_bind(hba); + if (cqe->un.link.port_speed == PHY_1GHZ_LINK) { + hba->linkspeed = LA_1GHZ_LINK; + } else { + hba->linkspeed = LA_10GHZ_LINK; } - /* Log the link event */ - emlxs_log_link_event(port); + hba->topology = TOPOLOGY_PT_PT; + hba->qos_linkspeed = cqe->un.link.qos_link_speed; + + (void) emlxs_fcf_linkup_notify(port); break; } break; case ASYNC_EVENT_CODE_FCOE_FIP: - fcoe = (CQE_ASYNC_FCOE_t *)cqe; - switch (fcoe->evt_type) { + switch (cqe->un.fcoe.evt_type) { case ASYNC_EVENT_NEW_FCF_DISC: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "FCOE Async Event New FCF %d:%d: received ", - fcoe->ref_index, fcoe->fcf_count); - (void) emlxs_fcf_bind(hba); + "FCOE Async Event: FCF_FOUND %d:%d", + cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); + + (void) emlxs_fcf_found_notify(port, + cqe->un.fcoe.ref_index); break; case ASYNC_EVENT_FCF_TABLE_FULL: - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "FCOE Async Event FCF Table Full %d:%d: received ", - fcoe->ref_index, fcoe->fcf_count); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "FCOE Async Event: FCFTAB_FULL %d:%d", + cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); + + (void) emlxs_fcf_full_notify(port); break; case ASYNC_EVENT_FCF_DEAD: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "FCOE Async Event FCF Disappeared %d:%d: received ", - fcoe->ref_index, fcoe->fcf_count); - (void) emlxs_reset_link(hba, 1, 0); + "FCOE Async Event: FCF_LOST %d:%d", + cqe->un.fcoe.ref_index, cqe->un.fcoe.fcf_count); + + (void) emlxs_fcf_lost_notify(port, + cqe->un.fcoe.ref_index); break; case ASYNC_EVENT_VIRT_LINK_CLEAR: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "FCOE Async Event VLINK CLEAR %d: received ", - fcoe->ref_index); - if (fcoe->ref_index == hba->vpi_base) { - /* - * Bounce the link to force rediscovery for - * VPI 0. We are ignoring this event for - * all other VPIs for now. - */ - (void) emlxs_reset_link(hba, 1, 0); - } + "FCOE Async Event: CVL %d", + cqe->un.fcoe.ref_index); + + (void) emlxs_fcf_cvl_notify(port, + (cqe->un.fcoe.ref_index - hba->vpi_base)); + break; + + case ASYNC_EVENT_FCF_MODIFIED: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "FCOE Async Event: FCF_CHANGED %d", + cqe->un.fcoe.ref_index); + + (void) emlxs_fcf_changed_notify(port, + cqe->un.fcoe.ref_index); break; } break; case ASYNC_EVENT_CODE_DCBX: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "DCBX Async Event Code %d: Not supported ", + "DCBX Async Event Code %d: Not supported", cqe->event_code); break; + case ASYNC_EVENT_CODE_GRP_5: + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "Group 5 Async Event type %d", cqe->event_type); + if (cqe->event_type == ASYNC_EVENT_QOS_SPEED) { + hba->qos_linkspeed = cqe->un.qos.qos_link_speed; + } + break; default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "Unknown Async Event Code %d", cqe->event_code); @@ -3492,25 +3534,25 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) MAILBOX4 *mb; MATCHMAP *mbox_bp; MATCHMAP *mbox_nonembed; - MAILBOXQ *mbq; + MAILBOXQ *mbq = NULL; uint32_t size; uint32_t *iptr; int rc; off_t offset; - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CQ ENTRY: process mbox event"); - if (cqe->consumed && !cqe->completed) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CQ ENTRY: Entry comsumed but not completed"); + "CQ ENTRY: Mbox event. Entry consumed but not completed"); return; } + mutex_enter(&EMLXS_PORT_LOCK); switch (hba->mbox_queue_flag) { case 0: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, - "No mailbox active."); + "CQ ENTRY: Mbox event. No mailbox active."); + + mutex_exit(&EMLXS_PORT_LOCK); return; case MBX_POLL: @@ -3524,28 +3566,51 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) mutex_enter(&EMLXS_MBOX_LOCK); mbq = (MAILBOXQ *)hba->mbox_mbq; if (mbq) { + port = (emlxs_port_t *)mbq->port; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, - "Mailbox event. Completing Polled command."); + "CQ ENTRY: Mbox event. Completing Polled command."); mbq->flag |= MBQ_COMPLETED; } mutex_exit(&EMLXS_MBOX_LOCK); + mutex_exit(&EMLXS_PORT_LOCK); return; case MBX_SLEEP: case MBX_NOWAIT: - mutex_enter(&EMLXS_MBOX_LOCK); - mbq = (MAILBOXQ *)hba->mbox_mbq; - mutex_exit(&EMLXS_MBOX_LOCK); + /* Check mbox_timer, it acts as a service flag too */ + /* The first to service the mbox queue will clear the timer */ + if (hba->mbox_timer) { + hba->mbox_timer = 0; + + mutex_enter(&EMLXS_MBOX_LOCK); + mbq = (MAILBOXQ *)hba->mbox_mbq; + mutex_exit(&EMLXS_MBOX_LOCK); + } + + if (!mbq) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, + "Mailbox event. No service required."); + mutex_exit(&EMLXS_PORT_LOCK); + return; + } + mb = (MAILBOX4 *)mbq; + mutex_exit(&EMLXS_PORT_LOCK); break; default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, - "Invalid Mailbox flag (%x)."); + "CQ ENTRY: Mbox event. Invalid Mailbox flag (%x).", + hba->mbox_queue_flag); + + mutex_exit(&EMLXS_PORT_LOCK); return; } + /* Set port context */ + port = (emlxs_port_t *)mbq->port; + offset = (off_t)((uint64_t)((unsigned long) hba->sli.sli4.mq.addr.virt) - (uint64_t)((unsigned long) @@ -3558,10 +3623,15 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb, MAILBOX_CMD_SLI4_BSIZE); - emlxs_data_dump(hba, "MBOX CMP", (uint32_t *)hba->mbox_mqe, 12, 0); + if (mb->mbxCommand != MBX_HEARTBEAT) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "CQ ENTRY: Mbox event. Mbox complete. status=%x cmd=%x", + mb->mbxStatus, mb->mbxCommand); + + emlxs_data_dump(port, "MBOX CMP", (uint32_t *)hba->mbox_mqe, + 12, 0); + } - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Mbox cmpl: %x cmd: %x", mb->mbxStatus, mb->mbxCommand); if (mb->mbxCommand == MBX_SLI_CONFIG) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "Mbox sge_cnt: %d length: %d embed: %d", @@ -3608,7 +3678,7 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) mb->mbxStatus = MBXERR_DMA_ERROR; } #endif -emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0); +emlxs_data_dump(port, "EXT AREA", (uint32_t *)iptr, 24, 0); } /* Mailbox has been completely received at this point */ @@ -3667,7 +3737,7 @@ done: /* Attempt to send pending mailboxes */ rc = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); } } return; @@ -3684,6 +3754,8 @@ emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp) #endif IOCBQ *iocbq; IOCB *iocb; + uint32_t *iptr; + fc_packet_t *pkt; emlxs_wqe_t *wqe; iocbq = &sbp->iocbq; @@ -3727,6 +3799,13 @@ emlxs_CQE_to_IOCB(emlxs_hba_t *hba, CQE_CmplWQ_t *cqe, emlxs_buf_t *sbp) if (iocb->ULPSTATUS == 0) { iocb->unsli3.ext_iocb.rsplen = cqe->CmdSpecific; } + if (iocb->ULPSTATUS == IOSTAT_LS_RJT) { + /* For LS_RJT, the driver populates the rsp buffer */ + pkt = PRIV2PKT(sbp); + iptr = (uint32_t *)pkt->pkt_resp; + *iptr++ = ELS_CMD_LS_RJT; + *iptr = cqe->Parameter; + } break; case CMD_GEN_REQUEST64_CR: @@ -3758,7 +3837,7 @@ emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba) CHANNEL *cp; emlxs_buf_t *sbp; IOCBQ *iocbq; - uint32_t i; + uint16_t i; uint32_t trigger; CQE_CmplWQ_t cqe; @@ -3768,8 +3847,9 @@ emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba) if (sbp == NULL || sbp == STALE_PACKET) { continue; } - hba->fc_table[i] = NULL; + hba->fc_table[i] = STALE_PACKET; hba->io_count--; + sbp->iotag = 0; mutex_exit(&EMLXS_FCTAB_LOCK); cp = sbp->channel; @@ -3797,10 +3877,8 @@ emlxs_sli4_hba_flush_chipq(emlxs_hba_t *hba) iocbq->next = NULL; - sbp->xp->state &= ~RESOURCE_XRI_PENDING_IO; - /* Exchange is no longer busy on-chip, free it */ - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); if (!(sbp->pkt_flags & (PACKET_POLLED | PACKET_ALLOCATED))) { @@ -3843,9 +3921,12 @@ emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba, emlxs_port_t *port = &PPORT; CHANNEL *cp; uint16_t request_tag; + CQE_u *cq_entry; request_tag = cqe->RequestTag; + cq_entry = (CQE_u *)cqe; + /* 1 to 1 mapping between CQ and channel */ cp = cq->channelp; @@ -3854,6 +3935,10 @@ emlxs_sli4_process_oor_wqe_cmpl(emlxs_hba_t *hba, EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CQ ENTRY: OOR Cmpl: tag=%x", request_tag); + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "CQ ENTRY: %08x %08x %08x %08x", cq_entry->word[0], + cq_entry->word[1], cq_entry->word[2], cq_entry->word[3]); + } /* emlxs_sli4_process_oor_wqe_cmpl() */ @@ -3876,18 +3961,21 @@ emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe) /* 1 to 1 mapping between CQ and channel */ cp = cq->channelp; + mutex_enter(&EMLXS_FCTAB_LOCK); sbp = hba->fc_table[request_tag]; atomic_add_32(&hba->io_active, -1); if (sbp == STALE_PACKET) { cp->hbaCmplCmd_sbp++; + mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CQ ENTRY: Stale sbp. tag=%x. Dropping...", request_tag); return; } - if (!sbp || !(sbp->xp)) { + if (!sbp || !(sbp->xrip)) { cp->hbaCmplCmd++; + mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CQ ENTRY: NULL sbp %p. tag=%x. Dropping...", sbp, request_tag); @@ -3901,37 +3989,39 @@ emlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe) cp->hbaCmplCmd_sbp++; -#ifdef SFCT_SUPPORT - fct_cmd = sbp->fct_cmd; - if (fct_cmd) { - cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; - mutex_enter(&cmd_sbp->fct_mtx); - EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE); - mutex_exit(&cmd_sbp->fct_mtx); - } -#endif /* SFCT_SUPPORT */ - /* Copy entry to sbp's iocbq */ iocbq = &sbp->iocbq; emlxs_CQE_to_IOCB(hba, cqe, sbp); iocbq->next = NULL; - sbp->xp->state &= ~RESOURCE_XRI_PENDING_IO; if (cqe->XB) { /* Mark exchange as ABORT in progress */ - sbp->xp->state |= RESOURCE_XRI_ABORT_INP; + sbp->xrip->flag &= ~EMLXS_XRI_PENDING_IO; + sbp->xrip->flag |= EMLXS_XRI_ABORT_INP; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CQ ENTRY: ABORT INP: tag=%x xri=%x", request_tag, - sbp->xp->XRI); + sbp->xrip->XRI); - emlxs_sli4_free_xri(hba, sbp, 0); + emlxs_sli4_free_xri(hba, sbp, 0, 0); } else { /* Exchange is no longer busy on-chip, free it */ - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 0); } + mutex_exit(&EMLXS_FCTAB_LOCK); + +#ifdef SFCT_SUPPORT + fct_cmd = sbp->fct_cmd; + if (fct_cmd) { + cmd_sbp = (emlxs_buf_t *)fct_cmd->cmd_fca_private; + mutex_enter(&cmd_sbp->fct_mtx); + EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, EMLXS_FCT_IOCB_COMPLETE); + mutex_exit(&cmd_sbp->fct_mtx); + } +#endif /* SFCT_SUPPORT */ + /* * If this is NOT a polled command completion * or a driver allocated pkt, then defer pkt @@ -4097,9 +4187,9 @@ emlxs_sli4_rxq_put(emlxs_hba_t *hba, emlxs_iocbq_t *iocbq) static void -emlxs_sli4_rq_post(emlxs_hba_t *hba, uint16_t rqid) +emlxs_sli4_rq_post(emlxs_port_t *port, uint16_t rqid) { - emlxs_port_t *port = &PPORT; + emlxs_hba_t *hba = HBA; emlxs_rqdbu_t rqdb; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, @@ -4142,9 +4232,8 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, emlxs_wqe_t *wqe; CHANNEL *cp; uint16_t iotag; - XRIobj_t *xp; - RPIobj_t *rp = NULL; - FCFIobj_t *fp; + XRIobj_t *xrip; + RPIobj_t *rpip = NULL; uint32_t cmd; uint32_t posted = 0; uint32_t abort = 1; @@ -4155,7 +4244,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, data_rq = &hba->sli.sli4.rq[hdr_rqi + 1]; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "CQ ENTRY: Unsol Rcv: RQid=%d,%d index=%d status=%x " \ + "CQ ENTRY: Unsol Rcv: RQid=%d,%d index=%d status=%x " "hdr_size=%d data_size=%d", cqe->RQid, hdr_rqi, hdr_rq->host_index, cqe->Status, cqe->hdr_size, cqe->data_size); @@ -4219,7 +4308,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, sizeof (fc_frame_hdr_t)); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ HDR[%d]: rctl:%x type:%x " \ + "RQ HDR[%d]: rctl:%x type:%x " "sid:%x did:%x oxid:%x rxid:%x", host_index, fchdr.r_ctl, fchdr.type, fchdr.s_id, fchdr.d_id, fchdr.ox_id, fchdr.rx_id); @@ -4234,7 +4323,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, case 0: /* BLS */ if (fchdr.r_ctl != 0x81) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: Unexpected FC rctl (0x%x) " \ + "RQ ENTRY: Unexpected FC rctl (0x%x) " "received. Dropping...", fchdr.r_ctl); @@ -4258,7 +4347,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* Make sure there is a payload */ if (cqe->data_size == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "RQ ENTRY: Unsol Rcv: No ELS payload provided. " \ + "RQ ENTRY: Unsol Rcv: No ELS payload provided. " "Dropping..."); goto done; @@ -4273,7 +4362,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* Make sure there is a payload */ if (cqe->data_size == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "RQ ENTRY: Unsol Rcv: No CT payload provided. " \ + "RQ ENTRY: Unsol Rcv: No CT payload provided. " "Dropping..."); goto done; @@ -4300,7 +4389,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, if (fchdr.type != 0) { if (!(fchdr.f_ctl & F_CTL_FIRST_SEQ)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: First of sequence not" \ + "RQ ENTRY: %s: First of sequence not" " set. Dropping...", label); @@ -4310,7 +4399,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, if (fchdr.seq_cnt != 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Sequence count not zero (%d). " \ + "RQ ENTRY: %s: Sequence count not zero (%d). " "Dropping...", label, fchdr.seq_cnt); @@ -4333,7 +4422,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, if (!iocbq) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Out of IOCB " \ + "RQ ENTRY: %s: Out of IOCB " "resources. Dropping...", label); @@ -4347,7 +4436,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, if (!seq_mp) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Out of buffer " \ + "RQ ENTRY: %s: Out of buffer " "resources. Dropping...", label); @@ -4389,7 +4478,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* Check sequence order */ if (fchdr.seq_cnt != seq_cnt) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Out of order frame received " \ + "RQ ENTRY: %s: Out of order frame received " "(%d != %d). Dropping...", label, fchdr.seq_cnt, seq_cnt); @@ -4399,6 +4488,15 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* We now have an iocbq */ + if (!port->VPIobj.vfip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "RQ ENTRY: %s: No fabric connection. " + "Dropping...", + label); + + goto done; + } + /* Save the frame data to our seq buffer */ if (cqe->data_size && seq_mp) { /* Get the next data rqb */ @@ -4422,7 +4520,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* Check sequence length */ if ((seq_len + cqe->data_size) > seq_mp->size) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "RQ ENTRY: %s: Sequence buffer overflow. " \ + "RQ ENTRY: %s: Sequence buffer overflow. " "(%d > %d). Dropping...", label, (seq_len + cqe->data_size), seq_mp->size); @@ -4460,7 +4558,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, goto done; } - emlxs_sli4_rq_post(hba, hdr_rq->qid); + emlxs_sli4_rq_post(port, hdr_rq->qid); posted = 1; /* End of sequence found. Process request now. */ @@ -4513,7 +4611,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, wqe->un.BlsRsp.RemoteId = fchdr.s_id; wqe->PU = 0x3; - wqe->ContextTag = port->vpi + hba->vpi_base; + wqe->ContextTag = port->VPIobj.VPI; wqe->ContextType = WQE_VPI_CONTEXT; wqe->OXId = (volatile uint16_t) fchdr.ox_id; wqe->XRITag = 0xffff; @@ -4532,31 +4630,39 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, break; case 1: /* ELS */ + if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "RQ ENTRY: %s: Port not yet enabled. " + "Dropping...", + label); + + goto done; + } + cmd = *((uint32_t *)seq_mp->virt); cmd &= ELS_CMD_MASK; - rp = NULL; + rpip = NULL; if (cmd != ELS_CMD_LOGO) { - rp = EMLXS_NODE_TO_RPI(hba, node); + rpip = EMLXS_NODE_TO_RPI(port, node); } - if (!rp) { - fp = hba->sli.sli4.FCFIp; - rp = &fp->scratch_rpi; + if (!rpip) { + rpip = port->VPIobj.rpip; } - xp = emlxs_sli4_reserve_xri(hba, rp); + xrip = emlxs_sli4_reserve_xri(hba, rpip); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Out of exchange " \ + "RQ ENTRY: %s: Out of exchange " "resources. Dropping...", label); goto done; } - xp->rx_id = fchdr.ox_id; + xrip->rx_id = fchdr.ox_id; /* Build CMD_RCV_ELS64_CX */ iocb->un.rcvels64.elsReq.tus.f.bdeFlags = 0; @@ -4569,13 +4675,13 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, iocb->un.rcvels64.parmRo = fchdr.d_id; iocb->ULPPU = 0x3; - iocb->ULPCONTEXT = xp->XRI; + iocb->ULPCONTEXT = xrip->XRI; iocb->ULPIOTAG = ((node)? node->nlp_Rpi:0); iocb->ULPCLASS = CLASS3; iocb->ULPCOMMAND = CMD_RCV_ELS64_CX; iocb->unsli3.ext_rcv.seq_len = seq_len; - iocb->unsli3.ext_rcv.vpi = port->vpi + hba->vpi_base; + iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI; if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { iocb->unsli3.ext_rcv.ccpe = 1; @@ -4588,39 +4694,47 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, break; case 0x20: /* CT */ + if (!(port->VPIobj.flag & EMLXS_VPI_PORT_ENABLED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "RQ ENTRY: %s: Port not yet enabled. " + "Dropping...", + label); + + goto done; + } if (!node) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Node not found (did=%x). " \ + "RQ ENTRY: %s: Node not found (did=%x). " "Dropping...", label, fchdr.d_id); goto done; } - rp = EMLXS_NODE_TO_RPI(hba, node); + rpip = EMLXS_NODE_TO_RPI(port, node); - if (!rp) { + if (!rpip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: RPI not found (did=%x rpi=%x). " \ + "RQ ENTRY: %s: RPI not found (did=%x rpi=%x). " "Dropping...", label, fchdr.d_id, node->nlp_Rpi); goto done; } - xp = emlxs_sli4_reserve_xri(hba, rp); + xrip = emlxs_sli4_reserve_xri(hba, rpip); - if (!xp) { + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RQ ENTRY: %s: Out of exchange " \ + "RQ ENTRY: %s: Out of exchange " "resources. Dropping...", label); goto done; } - xp->rx_id = fchdr.ox_id; + xrip->rx_id = fchdr.ox_id; /* Build CMD_RCV_SEQ64_CX */ iocb->un.rcvseq64.rcvBde.tus.f.bdeFlags = 0; @@ -4636,13 +4750,13 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, iocb->un.rcvseq64.w5.hcsw.Fctl = fchdr.f_ctl; iocb->ULPPU = 0x3; - iocb->ULPCONTEXT = xp->XRI; - iocb->ULPIOTAG = rp->RPI; + iocb->ULPCONTEXT = xrip->XRI; + iocb->ULPIOTAG = rpip->RPI; iocb->ULPCLASS = CLASS3; iocb->ULPCOMMAND = CMD_RCV_SEQ64_CX; iocb->unsli3.ext_rcv.seq_len = seq_len; - iocb->unsli3.ext_rcv.vpi = port->vpi + hba->vpi_base; + iocb->unsli3.ext_rcv.vpi = port->VPIobj.VPI; if (fchdr.f_ctl & F_CTL_CHAINED_SEQ) { iocb->unsli3.ext_rcv.ccpe = 1; @@ -4661,7 +4775,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, done: if (!posted) { - emlxs_sli4_rq_post(hba, hdr_rq->qid); + emlxs_sli4_rq_post(port, hdr_rq->qid); } if (abort) { @@ -4673,11 +4787,10 @@ done: /* Return memory resources to pools */ if (iocbq) { if (iocbq->bp) { - (void) emlxs_mem_put(hba, buf_type, - (uint8_t *)iocbq->bp); + emlxs_mem_put(hba, buf_type, (void *)iocbq->bp); } - (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); + emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); } #ifdef FMA_SUPPORT @@ -4690,7 +4803,7 @@ done: hba->sli.sli4.slim2.dma_handle); emlxs_thread_spawn(hba, emlxs_restart_thread, - NULL, NULL); + 0, 0); } #endif return; @@ -4704,12 +4817,16 @@ emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_XRI_Abort_t *cqe) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; - xp = emlxs_sli4_find_xri(hba, cqe->XRI); - if (xp == NULL) { + mutex_enter(&EMLXS_FCTAB_LOCK); + + xrip = emlxs_sli4_find_xri(hba, cqe->XRI); + if (xrip == NULL) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, "CQ ENTRY: process xri aborted ignored"); + + mutex_exit(&EMLXS_FCTAB_LOCK); return; } @@ -4717,15 +4834,21 @@ emlxs_sli4_process_xri_aborted(emlxs_hba_t *hba, CQ_DESC_t *cq, "CQ ENTRY: process xri x%x aborted: IA %d EO %d BR %d", cqe->XRI, cqe->IA, cqe->EO, cqe->BR); - if (!(xp->state & RESOURCE_XRI_ABORT_INP)) { + if (!(xrip->flag & EMLXS_XRI_ABORT_INP)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, "XRI Aborted: Bad state: x%x xri x%x", - xp->state, xp->XRI); + xrip->flag, xrip->XRI); + + mutex_exit(&EMLXS_FCTAB_LOCK); return; } /* Exchange is no longer busy on-chip, free it */ - emlxs_sli4_free_xri(hba, 0, xp); + emlxs_sli4_free_xri(hba, 0, xrip, 0); + + mutex_exit(&EMLXS_FCTAB_LOCK); + + return; } /* emlxs_sli4_process_xri_aborted () */ @@ -4963,14 +5086,10 @@ emlxs_sli4_msi_intr(char *arg1, char *arg2) if (msgid >= hba->intr_count) { msgid = 0; } - - mutex_enter(&EMLXS_INTR_LOCK(msgid)); - mutex_enter(&EMLXS_PORT_LOCK); if ((hba->state == FC_KILLED) || (hba->flag & FC_OFFLINE_MODE)) { mutex_exit(&EMLXS_PORT_LOCK); - mutex_exit(&EMLXS_INTR_LOCK(msgid)); return (DDI_INTR_UNCLAIMED); } @@ -4978,7 +5097,6 @@ emlxs_sli4_msi_intr(char *arg1, char *arg2) emlxs_sli4_process_eq(hba, &hba->sli.sli4.eq[msgid]); mutex_exit(&EMLXS_PORT_LOCK); - mutex_exit(&EMLXS_INTR_LOCK(msgid)); return (DDI_INTR_CLAIMED); } /* emlxs_sli4_msi_intr() */ @@ -5102,21 +5220,7 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) MBUF_INFO *buf_info; uint32_t i; - if (hba->sli.sli4.FCFIp) { - kmem_free(hba->sli.sli4.FCFIp, - (sizeof (FCFIobj_t) * hba->sli.sli4.FCFICount)); - hba->sli.sli4.FCFIp = NULL; - } - if (hba->sli.sli4.VFIp) { - kmem_free(hba->sli.sli4.VFIp, - (sizeof (VFIobj_t) * hba->sli.sli4.VFICount)); - hba->sli.sli4.VFIp = NULL; - } - if (hba->sli.sli4.RPIp) { - kmem_free(hba->sli.sli4.RPIp, - (sizeof (RPIobj_t) * hba->sli.sli4.RPICount)); - hba->sli.sli4.RPIp = NULL; - } + emlxs_fcf_fini(hba); buf_info = &hba->sli.sli4.HeaderTmplate; if (buf_info->virt) { @@ -5128,7 +5232,7 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) || (hba->sli.sli4.XRIinuse_b != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, "XRIs inuse during free!: %p %p != %p\n", hba->sli.sli4.XRIinuse_f, hba->sli.sli4.XRIinuse_b, @@ -5183,8 +5287,6 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) hba->sli.sli4.wq_map[i] = 0xffff; } - mutex_destroy(&hba->sli.sli4.id_lock); - } /* emlxs_sli4_resource_free() */ @@ -5197,14 +5299,11 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) uint16_t index; int num_eq; int num_wq; - uint32_t i; + uint16_t i; uint32_t j; uint32_t k; uint32_t word; - FCFIobj_t *fp; - VFIobj_t *vp; - RPIobj_t *rp; - XRIobj_t *xp; + XRIobj_t *xrip; char buf[64]; RQE_t *rqe; MBUF_INFO *rqb; @@ -5218,50 +5317,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) off_t offset; uint32_t count = 0; - (void) sprintf(buf, "%s_id_lock mutex", DRIVER_NAME); - mutex_init(&hba->sli.sli4.id_lock, buf, MUTEX_DRIVER, NULL); - - if ((!hba->sli.sli4.FCFIp) && (hba->sli.sli4.FCFICount)) { - hba->sli.sli4.FCFIp = (FCFIobj_t *)kmem_zalloc( - (sizeof (FCFIobj_t) * hba->sli.sli4.FCFICount), KM_SLEEP); - - fp = hba->sli.sli4.FCFIp; - index = 0; /* Start FCFIs at 0 */ - for (i = 0; i < hba->sli.sli4.FCFICount; i++) { - fp->FCFI = index; - fp->index = i; - fp++; - index++; - } - } - - if ((!hba->sli.sli4.VFIp) && (hba->sli.sli4.VFICount)) { - hba->sli.sli4.VFIp = (VFIobj_t *)kmem_zalloc( - (sizeof (VFIobj_t) * hba->sli.sli4.VFICount), KM_SLEEP); - - vp = hba->sli.sli4.VFIp; - index = hba->sli.sli4.VFIBase; - for (i = 0; i < hba->sli.sli4.VFICount; i++) { - vp->VFI = index; - vp->index = i; - vp++; - index++; - } - } - - if ((!hba->sli.sli4.RPIp) && (hba->sli.sli4.RPICount)) { - hba->sli.sli4.RPIp = (RPIobj_t *)kmem_zalloc( - (sizeof (RPIobj_t) * hba->sli.sli4.RPICount), KM_SLEEP); - - rp = hba->sli.sli4.RPIp; - index = hba->sli.sli4.RPIBase; - for (i = 0; i < hba->sli.sli4.RPICount; i++) { - rp->RPI = index; - rp->index = i; /* offset into HdrTmplate */ - rp++; - index++; - } - } + emlxs_fcf_init(hba); /* EQs - 1 per Interrupt vector */ num_eq = hba->intr_count; @@ -5322,7 +5378,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; @@ -5348,7 +5404,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; @@ -5370,7 +5426,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; @@ -5392,7 +5448,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; @@ -5424,7 +5480,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; @@ -5462,7 +5518,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) FC_MBUF_SNGLSG | FC_MBUF_DMA32; rqb->align = ddi_ptob(hba->dip, 1L); rqb->phys = phys; - rqb->virt = virt; + rqb->virt = (void *)virt; rqb->data_handle = data_handle; rqb->dma_handle = dma_handle; @@ -5505,41 +5561,41 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc( (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP); - xp = hba->sli.sli4.XRIp; + xrip = hba->sli.sli4.XRIp; index = hba->sli.sli4.XRIBase; size = hba->sli.sli4.mem_sgl_size; for (i = 0; i < hba->sli.sli4.XRICount; i++) { - xp->sge_count = + xrip->sge_count = (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64)); - xp->XRI = index; - xp->iotag = i; - if ((xp->XRI == 0) || (xp->iotag == 0)) { + xrip->XRI = index; + xrip->iotag = i; + if ((xrip->XRI == 0) || (xrip->iotag == 0)) { index++; /* Skip XRI 0 or IOTag 0 */ - xp++; + xrip++; continue; } - /* Add xp to end of free list */ - xp->_b = hba->sli.sli4.XRIfree_b; - hba->sli.sli4.XRIfree_b->_f = xp; - xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; - hba->sli.sli4.XRIfree_b = xp; + /* Add xrip to end of free list */ + xrip->_b = hba->sli.sli4.XRIfree_b; + hba->sli.sli4.XRIfree_b->_f = xrip; + xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.XRIfree_b = xrip; hba->sli.sli4.xrif_count++; - /* Allocate SGL for this xp */ - buf_info = &xp->SGList; + /* Allocate SGL for this xrip */ + buf_info = &xrip->SGList; buf_info->size = size; buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; buf_info->align = size; buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; phys += size; virt += size; - xp++; + xrip++; index++; } } @@ -5552,7 +5608,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) buf_info->flags = FC_MBUF_DMA | FC_MBUF_DMA32; buf_info->align = ddi_ptob(hba->dip, 1L); buf_info->phys = phys; - buf_info->virt = virt; + buf_info->virt = (void *)virt; buf_info->data_handle = data_handle; buf_info->dma_handle = dma_handle; } @@ -5581,161 +5637,18 @@ failed: } /* emlxs_sli4_resource_alloc */ -static FCFIobj_t * -emlxs_sli4_alloc_fcfi(emlxs_hba_t *hba) -{ - emlxs_port_t *port = &PPORT; - uint32_t i; - FCFIobj_t *fp; - - mutex_enter(&hba->sli.sli4.id_lock); - fp = hba->sli.sli4.FCFIp; - for (i = 0; i < hba->sli.sli4.FCFICount; i++) { - if (fp->state == RESOURCE_FREE) { - fp->state = RESOURCE_ALLOCATED; - mutex_exit(&hba->sli.sli4.id_lock); - return (fp); - } - fp++; - } - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to Alloc FCFI"); - return (NULL); - -} /* emlxs_sli4_alloc_fcfi() */ - - -static FCFIobj_t * -emlxs_sli4_find_fcfi_fcfrec(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec) -{ - emlxs_port_t *port = &PPORT; - uint32_t i; - FCFIobj_t *fp; - - /* Check for BOTH a matching FCF index and mac address */ - mutex_enter(&hba->sli.sli4.id_lock); - fp = hba->sli.sli4.FCFIp; - for (i = 0; i < hba->sli.sli4.FCFICount; i++) { - if (fp->state & RESOURCE_ALLOCATED) { - if ((fp->FCF_index == fcfrec->fcf_index) && - (bcmp((char *)fcfrec->fcf_mac_address_hi, - fp->fcf_rec.fcf_mac_address_hi, 4) == 0) && - (bcmp((char *)fcfrec->fcf_mac_address_low, - fp->fcf_rec.fcf_mac_address_low, 2) == 0)) { - mutex_exit(&hba->sli.sli4.id_lock); - return (fp); - } - } - fp++; - } - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to Find FCF Index %d", fcfrec->fcf_index); - return (0); - -} /* emlxs_sli4_find_fcfi_fcfrec() */ - - -extern VFIobj_t * -emlxs_sli4_alloc_vfi(emlxs_hba_t *hba, FCFIobj_t *fp) -{ - emlxs_port_t *port = &PPORT; - uint32_t i; - VFIobj_t *vp; - - mutex_enter(&hba->sli.sli4.id_lock); - vp = hba->sli.sli4.VFIp; - for (i = 0; i < hba->sli.sli4.VFICount; i++) { - if (vp->state == RESOURCE_FREE) { - vp->state = RESOURCE_ALLOCATED; - vp->FCFIp = fp; - fp->outstandingVFIs++; - mutex_exit(&hba->sli.sli4.id_lock); - return (vp); - } - vp++; - } - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to Alloc VFI"); - return (NULL); - -} /* emlxs_sli4_alloc_vfi() */ - - -extern RPIobj_t * -emlxs_sli4_alloc_rpi(emlxs_port_t *port) -{ - emlxs_hba_t *hba = HBA; - uint32_t i; - RPIobj_t *rp; - - mutex_enter(&hba->sli.sli4.id_lock); - rp = hba->sli.sli4.RPIp; - for (i = 0; i < hba->sli.sli4.RPICount; i++) { - /* To be consistent with SLI3, the RPI assignment */ - /* starts with 1. ONLY one SLI4 HBA in the entire */ - /* system will be sacrificed by one RPI and that */ - /* is the one having RPI base equal 0. */ - if ((rp->state == RESOURCE_FREE) && (rp->RPI != 0)) { - rp->state = RESOURCE_ALLOCATED; - rp->VPIp = port; - port->outstandingRPIs++; - mutex_exit(&hba->sli.sli4.id_lock); - return (rp); - } - rp++; - } - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to Alloc RPI"); - return (NULL); - -} /* emlxs_sli4_alloc_rpi() */ - - -extern RPIobj_t * -emlxs_sli4_find_rpi(emlxs_hba_t *hba, uint16_t rpi) -{ - emlxs_port_t *port = &PPORT; - RPIobj_t *rp; - int index; - - rp = hba->sli.sli4.RPIp; - index = rpi - hba->sli.sli4.RPIBase; - if ((rpi == 0xffff) || (index >= hba->sli.sli4.RPICount)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "RPI %d out of range: Count = %d", - index, hba->sli.sli4.RPICount); - return (NULL); - } - rp += index; - mutex_enter(&hba->sli.sli4.id_lock); - if ((index < 0) || !(rp->state & RESOURCE_ALLOCATED)) { - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to find RPI %d", index); - return (NULL); - } - mutex_exit(&hba->sli.sli4.id_lock); - return (rp); - -} /* emlxs_sli4_find_rpi() */ - - static XRIobj_t * -emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp) +emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rpip) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; uint16_t iotag; mutex_enter(&EMLXS_FCTAB_LOCK); - xp = hba->sli.sli4.XRIfree_f; + xrip = hba->sli.sli4.XRIfree_f; - if (xp == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { + if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, @@ -5744,11 +5657,11 @@ emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp) return (NULL); } - iotag = xp->iotag; + iotag = xrip->iotag; if ((!iotag) || - (hba->fc_table[iotag] != NULL && - hba->fc_table[iotag] != STALE_PACKET)) { + ((hba->fc_table[iotag] != NULL) && + (hba->fc_table[iotag] != STALE_PACKET))) { /* * No more command slots available, retry later */ @@ -5759,88 +5672,106 @@ emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp) return (NULL); } - xp->state = (RESOURCE_ALLOCATED | RESOURCE_XRI_RESERVED); - xp->RPIp = rp; - xp->sbp = NULL; + xrip->state = XRI_STATE_ALLOCATED; + xrip->flag = EMLXS_XRI_RESERVED; + xrip->rpip = rpip; + xrip->sbp = NULL; - if (rp) { - rp->outstandingXRIs++; + if (rpip) { + rpip->xri_count++; } /* Take it off free list */ - (xp->_b)->_f = xp->_f; - (xp->_f)->_b = xp->_b; - xp->_f = NULL; - xp->_b = NULL; + (xrip->_b)->_f = xrip->_f; + (xrip->_f)->_b = xrip->_b; + xrip->_f = NULL; + xrip->_b = NULL; hba->sli.sli4.xrif_count--; /* Add it to end of inuse list */ - xp->_b = hba->sli.sli4.XRIinuse_b; - hba->sli.sli4.XRIinuse_b->_f = xp; - xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; - hba->sli.sli4.XRIinuse_b = xp; + xrip->_b = hba->sli.sli4.XRIinuse_b; + hba->sli.sli4.XRIinuse_b->_f = xrip; + xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; + hba->sli.sli4.XRIinuse_b = xrip; hba->sli.sli4.xria_count++; mutex_exit(&EMLXS_FCTAB_LOCK); - return (xp); + return (xrip); } /* emlxs_sli4_reserve_xri() */ extern uint32_t -emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri) +emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri, uint32_t lock) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; + + if (lock) { + mutex_enter(&EMLXS_FCTAB_LOCK); + } - xp = emlxs_sli4_find_xri(hba, xri); + xrip = emlxs_sli4_find_xri(hba, xri); - mutex_enter(&EMLXS_FCTAB_LOCK); + if (!xrip || xrip->state == XRI_STATE_FREE) { + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } - if (!xp || xp->state == RESOURCE_FREE) { - mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "emlxs_sli4_unreserve_xri: xri=%x already freed.", xp->XRI); + "emlxs_sli4_unreserve_xri: xri=%x already freed.", + xrip->XRI); return (0); } - if (!(xp->state & RESOURCE_XRI_RESERVED)) { - mutex_exit(&EMLXS_FCTAB_LOCK); + if (!(xrip->flag & EMLXS_XRI_RESERVED)) { + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "emlxs_sli4_unreserve_xri: xri=%x in use.", xp->XRI); + "emlxs_sli4_unreserve_xri: xri=%x in use.", xrip->XRI); return (1); } - if (hba->fc_table[xp->iotag]) { - hba->fc_table[xp->iotag] = NULL; + if (xrip->iotag && + (hba->fc_table[xrip->iotag] != NULL) && + (hba->fc_table[xrip->iotag] != STALE_PACKET)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, + "emlxs_sli4_unreserve_xri:%x sbp dropped:%p", + xrip->XRI, hba->fc_table[xrip->iotag]); + + hba->fc_table[xrip->iotag] = NULL; hba->io_count--; } - xp->state = RESOURCE_FREE; + xrip->state = XRI_STATE_FREE; - if (xp->RPIp) { - xp->RPIp->outstandingXRIs--; - xp->RPIp = NULL; + if (xrip->rpip) { + xrip->rpip->xri_count--; + xrip->rpip = NULL; } /* Take it off inuse list */ - (xp->_b)->_f = xp->_f; - (xp->_f)->_b = xp->_b; - xp->_f = NULL; - xp->_b = NULL; + (xrip->_b)->_f = xrip->_f; + (xrip->_f)->_b = xrip->_b; + xrip->_f = NULL; + xrip->_b = NULL; hba->sli.sli4.xria_count--; /* Add it to end of free list */ - xp->_b = hba->sli.sli4.XRIfree_b; - hba->sli.sli4.XRIfree_b->_f = xp; - xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; - hba->sli.sli4.XRIfree_b = xp; + xrip->_b = hba->sli.sli4.XRIfree_b; + hba->sli.sli4.XRIfree_b->_f = xrip; + xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.XRIfree_b = xrip; hba->sli.sli4.xrif_count++; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "emlxs_sli4_unreserve_xri: xri=%x unreserved.", xp->XRI); + "emlxs_sli4_unreserve_xri: xri=%x unreserved.", xrip->XRI); - mutex_exit(&EMLXS_FCTAB_LOCK); + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } return (0); @@ -5852,13 +5783,13 @@ emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri) { emlxs_port_t *port = &PPORT; uint16_t iotag; - XRIobj_t *xp; - - xp = emlxs_sli4_find_xri(hba, xri); + XRIobj_t *xrip; mutex_enter(&EMLXS_FCTAB_LOCK); - if (!xp) { + xrip = emlxs_sli4_find_xri(hba, xri); + + if (!xrip) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, "emlxs_sli4_register_xri: XRI not found."); @@ -5867,25 +5798,26 @@ emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri) return (NULL); } - if (!(xp->state & RESOURCE_ALLOCATED) || - !(xp->state & RESOURCE_XRI_RESERVED)) { + if ((xrip->state == XRI_STATE_FREE) || + !(xrip->flag & EMLXS_XRI_RESERVED)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "emlxs_sli4_register_xri: Invalid XRI. xp=%p state=%x", - xp, xp->state); + "emlxs_sli4_register_xri: Invalid XRI. xrip=%p " + "state=%x flag=%x", + xrip, xrip->state, xrip->flag); mutex_exit(&EMLXS_FCTAB_LOCK); return (NULL); } - iotag = xp->iotag; + iotag = xrip->iotag; if ((!iotag) || - (hba->fc_table[iotag] != NULL && - hba->fc_table[iotag] != STALE_PACKET)) { + ((hba->fc_table[iotag] != NULL) && + (hba->fc_table[iotag] != STALE_PACKET))) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "emlxs_sli4_register_xri: Invalid fc_table entry. " \ + "emlxs_sli4_register_xri: Invalid fc_table entry. " "iotag=%x entry=%p", iotag, hba->fc_table[iotag]); @@ -5897,50 +5829,48 @@ emlxs_sli4_register_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t xri) hba->io_count++; sbp->iotag = iotag; - sbp->xp = xp; + sbp->xrip = xrip; - xp->state &= ~RESOURCE_XRI_RESERVED; - xp->sbp = sbp; + xrip->flag &= ~EMLXS_XRI_RESERVED; + xrip->sbp = sbp; mutex_exit(&EMLXS_FCTAB_LOCK); - return (xp); + return (xrip); } /* emlxs_sli4_register_xri() */ /* Performs both reserve and register functions for XRI */ static XRIobj_t * -emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rp) +emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rpip) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; uint16_t iotag; mutex_enter(&EMLXS_FCTAB_LOCK); - xp = hba->sli.sli4.XRIfree_f; + xrip = hba->sli.sli4.XRIfree_f; - if (xp == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { + if (xrip == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { mutex_exit(&EMLXS_FCTAB_LOCK); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, - "Unable to allocate XRI"); - return (NULL); } /* Get the iotag by registering the packet */ - iotag = xp->iotag; + iotag = xrip->iotag; if ((!iotag) || - (hba->fc_table[iotag] != NULL && - hba->fc_table[iotag] != STALE_PACKET)) { + ((hba->fc_table[iotag] != NULL) && + (hba->fc_table[iotag] != STALE_PACKET))) { /* * No more command slots available, retry later */ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "Adapter Busy. Unable to allocate iotag"); + "Adapter Busy. Unable to alloc iotag:(0x%x)(%p)", + iotag, hba->fc_table[iotag]); mutex_exit(&EMLXS_FCTAB_LOCK); return (NULL); @@ -5950,304 +5880,146 @@ emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rp) hba->io_count++; sbp->iotag = iotag; - sbp->xp = xp; + sbp->xrip = xrip; - xp->state = RESOURCE_ALLOCATED; - xp->RPIp = rp; - xp->sbp = sbp; + xrip->state = XRI_STATE_ALLOCATED; + xrip->flag = 0; + xrip->rpip = rpip; + xrip->sbp = sbp; - if (rp) { - rp->outstandingXRIs++; + if (rpip) { + rpip->xri_count++; } /* Take it off free list */ - (xp->_b)->_f = xp->_f; - (xp->_f)->_b = xp->_b; - xp->_f = NULL; - xp->_b = NULL; + (xrip->_b)->_f = xrip->_f; + (xrip->_f)->_b = xrip->_b; + xrip->_f = NULL; + xrip->_b = NULL; hba->sli.sli4.xrif_count--; /* Add it to end of inuse list */ - xp->_b = hba->sli.sli4.XRIinuse_b; - hba->sli.sli4.XRIinuse_b->_f = xp; - xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; - hba->sli.sli4.XRIinuse_b = xp; + xrip->_b = hba->sli.sli4.XRIinuse_b; + hba->sli.sli4.XRIinuse_b->_f = xrip; + xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; + hba->sli.sli4.XRIinuse_b = xrip; hba->sli.sli4.xria_count++; mutex_exit(&EMLXS_FCTAB_LOCK); - return (xp); + return (xrip); } /* emlxs_sli4_alloc_xri() */ +/* EMLXS_FCTAB_LOCK must be held to enter */ extern XRIobj_t * emlxs_sli4_find_xri(emlxs_hba_t *hba, uint16_t xri) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; - mutex_enter(&EMLXS_FCTAB_LOCK); - xp = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; - while (xp != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { - if ((xp->state & RESOURCE_ALLOCATED) && - (xp->XRI == xri)) { - break; + xrip = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; + while (xrip != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { + if ((xrip->state >= XRI_STATE_ALLOCATED) && + (xrip->XRI == xri)) { + return (xrip); } - xp = xp->_f; - } - mutex_exit(&EMLXS_FCTAB_LOCK); - - if (xp == (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Unable to find XRI x%x", xri); - return (NULL); + xrip = xrip->_f; } - return (xp); - -} /* emlxs_sli4_find_xri() */ - -extern void -emlxs_sli4_free_fcfi(emlxs_hba_t *hba, FCFIobj_t *fp) -{ - emlxs_port_t *port = &PPORT; - - mutex_enter(&hba->sli.sli4.id_lock); - if (fp->state == RESOURCE_FREE) { - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free FCFI:%d idx:%d, Already freed", - fp->FCFI, fp->FCF_index); - return; - } - - if (fp->outstandingVFIs) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free FCFI:%d, %d outstanding VFIs", fp->FCFI, - fp->outstandingVFIs); - } - fp->state = RESOURCE_FREE; - fp->FCF_index = 0; - bzero(&fp->fcf_rec, sizeof (FCF_RECORD_t)); - fp->fcf_vfi = 0; - fp->fcf_vpi = 0; - - mutex_exit(&hba->sli.sli4.id_lock); - -} /* emlxs_sli4_free_fcfi() */ - - -extern void -emlxs_sli4_free_vfi(emlxs_hba_t *hba, VFIobj_t *fp) -{ - emlxs_port_t *port = &PPORT; - - mutex_enter(&hba->sli.sli4.id_lock); - if (fp->state == RESOURCE_FREE) { - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free VFI:%d, Already freed", fp->VFI); - return; - } - - if (fp->outstandingVPIs) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free VFI:%d, %d outstanding VPIs", fp->VFI, - fp->outstandingVPIs); - } - fp->state = RESOURCE_FREE; - fp->FCFIp->outstandingVFIs--; - mutex_exit(&hba->sli.sli4.id_lock); - - if ((fp->FCFIp->outstandingVFIs == 0) && - (hba->state == FC_LINK_DOWN)) { - - /* No more VPIs so unreg the VFI */ - (void) emlxs_mb_unreg_fcfi(hba, fp->FCFIp); - } - fp->FCFIp = NULL; - - -} /* emlxs_sli4_free_vfi() */ - - -static void -emlxs_sli4_free_vpi(emlxs_hba_t *hba, emlxs_port_t *pp) -{ - emlxs_port_t *port = &PPORT; - - if (!(pp->flag & EMLXS_PORT_ENABLE)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free VPI:%d, Already freed", pp->vpi); - return; - } - - mutex_enter(&hba->sli.sli4.id_lock); - if (pp->outstandingRPIs) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free VPI:%d, %d outstanding RPIs", pp->vpi, - pp->outstandingRPIs); - } - pp->VFIp->outstandingVPIs--; - if (pp->VFIp->outstandingVPIs == 0) { - /* No more VPIs so unreg the VFI */ - (void) emlxs_mb_unreg_vfi(hba, pp->VFIp); - } - - pp->VFIp = NULL; - mutex_exit(&hba->sli.sli4.id_lock); - -} /* emlxs_sli4_free_vpi() */ + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "Unable to find XRI x%x", xri); -static void -emlxs_sli4_cmpl_io(emlxs_hba_t *hba, emlxs_buf_t *sbp) -{ - CHANNEL *cp; - IOCBQ *iocbq; - CQE_u cq_entry; + return (NULL); - cp = sbp->channel; - iocbq = &sbp->iocbq; +} /* emlxs_sli4_find_xri() */ - bzero((void *) &cq_entry, sizeof (CQE_u)); - cq_entry.cqCmplEntry.Status = IOSTAT_LOCAL_REJECT; - cq_entry.cqCmplEntry.Parameter = IOERR_SEQUENCE_TIMEOUT; - cq_entry.cqCmplEntry.RequestTag = sbp->iotag; - emlxs_CQE_to_IOCB(hba, &cq_entry.cqCmplEntry, sbp); - /* - * If this is NOT a polled command completion - * or a driver allocated pkt, then defer pkt - * completion. - */ - if (!(sbp->pkt_flags & - (PACKET_POLLED | PACKET_ALLOCATED))) { - /* Add the IOCB to the channel list */ - mutex_enter(&cp->rsp_lock); - if (cp->rsp_head == NULL) { - cp->rsp_head = iocbq; - cp->rsp_tail = iocbq; - } else { - cp->rsp_tail->next = iocbq; - cp->rsp_tail = iocbq; - } - mutex_exit(&cp->rsp_lock); - /* Delay triggering thread till end of ISR */ - cp->chan_flag |= EMLXS_NEEDS_TRIGGER; - } else { - emlxs_proc_channel_event(hba, cp, iocbq); - } -} /* emlxs_sli4_cmpl_io() */ extern void -emlxs_sli4_free_rpi(emlxs_hba_t *hba, RPIobj_t *rp) +emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xrip, + uint8_t lock) { emlxs_port_t *port = &PPORT; - XRIobj_t *xp; - XRIobj_t *next_xp; - mutex_enter(&hba->sli.sli4.id_lock); - if (rp->state == RESOURCE_FREE) { - mutex_exit(&hba->sli.sli4.id_lock); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free RPI:%d, Already freed", rp->RPI); - return; - } - if (rp->outstandingXRIs) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free RPI:%d, %d outstanding XRIs", rp->RPI, - rp->outstandingXRIs); - } - rp->state = RESOURCE_FREE; - rp->VPIp = NULL; - mutex_exit(&hba->sli.sli4.id_lock); - - /* Break node/RPI binding */ - if (rp->node) { - rw_enter(&port->node_rwlock, RW_WRITER); - rp->node->RPIp = NULL; - rp->node = NULL; - rw_exit(&port->node_rwlock); + if (lock) { + mutex_enter(&EMLXS_FCTAB_LOCK); } - mutex_enter(&EMLXS_FCTAB_LOCK); - /* Remove all XRIs under this RPI */ - xp = (XRIobj_t *)hba->sli.sli4.XRIinuse_f; - while (xp != (XRIobj_t *)&hba->sli.sli4.XRIinuse_f) { - next_xp = xp->_f; - if ((xp->state & RESOURCE_ALLOCATED) && - (xp->RPIp == rp)) { - xp->RPIp->outstandingXRIs--; - xp->RPIp = NULL; - } - xp = next_xp; - } - mutex_exit(&EMLXS_FCTAB_LOCK); - -} /* emlxs_sli4_free_rpi() */ - - -extern void -emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xp) -{ - emlxs_port_t *port = &PPORT; - - mutex_enter(&EMLXS_FCTAB_LOCK); - if (xp) { - if (xp->state == RESOURCE_FREE) { - mutex_exit(&EMLXS_FCTAB_LOCK); + if (xrip) { + if (xrip->state == XRI_STATE_FREE) { + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Free XRI:%x, Already freed", xp->XRI); + "Free XRI:%x, Already freed", xrip->XRI); return; } - if (hba->fc_table[xp->iotag]) { - hba->fc_table[xp->iotag] = NULL; + if (xrip->iotag && + (hba->fc_table[xrip->iotag] != NULL) && + (hba->fc_table[xrip->iotag] != STALE_PACKET)) { + hba->fc_table[xrip->iotag] = NULL; hba->io_count--; } - xp->state = RESOURCE_FREE; + xrip->state = XRI_STATE_FREE; + xrip->flag = 0; - if (xp->RPIp) { - xp->RPIp->outstandingXRIs--; - xp->RPIp = NULL; + if (xrip->rpip) { + xrip->rpip->xri_count--; + xrip->rpip = NULL; } /* Take it off inuse list */ - (xp->_b)->_f = xp->_f; - (xp->_f)->_b = xp->_b; - xp->_f = NULL; - xp->_b = NULL; + (xrip->_b)->_f = xrip->_f; + (xrip->_f)->_b = xrip->_b; + xrip->_f = NULL; + xrip->_b = NULL; hba->sli.sli4.xria_count--; /* Add it to end of free list */ - xp->_b = hba->sli.sli4.XRIfree_b; - hba->sli.sli4.XRIfree_b->_f = xp; - xp->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; - hba->sli.sli4.XRIfree_b = xp; + xrip->_b = hba->sli.sli4.XRIfree_b; + hba->sli.sli4.XRIfree_b->_f = xrip; + xrip->_f = (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.XRIfree_b = xrip; hba->sli.sli4.xrif_count++; } if (sbp) { - sbp->xp = 0; + if (!(sbp->pkt_flags & PACKET_VALID) || + (sbp->pkt_flags & + (PACKET_ULP_OWNED|PACKET_COMPLETED|PACKET_IN_COMPLETION))) { + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "Free XRI: sbp invalid. sbp=%p flags=%x xri=%x", + sbp, sbp->pkt_flags, ((xrip)? xrip->XRI:0)); + return; + } - if (xp && (xp->iotag != sbp->iotag)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, + sbp->xrip = 0; + + if (xrip && (xrip->iotag != sbp->iotag)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, "sbp / iotag mismatch %p iotag:%d %d", sbp, - sbp->iotag, xp->iotag); + sbp->iotag, xrip->iotag); } if (sbp->iotag) { - if (hba->fc_table[sbp->iotag]) { + if (sbp == hba->fc_table[sbp->iotag]) { hba->fc_table[sbp->iotag] = NULL; hba->io_count--; } sbp->iotag = 0; } - mutex_exit(&EMLXS_FCTAB_LOCK); + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } /* Clean up the sbp */ mutex_enter(&sbp->mtx); @@ -6263,7 +6035,9 @@ emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xp) mutex_exit(&sbp->mtx); } else { - mutex_exit(&EMLXS_FCTAB_LOCK); + if (lock) { + mutex_exit(&EMLXS_FCTAB_LOCK); + } } } /* emlxs_sli4_free_xri() */ @@ -6274,7 +6048,7 @@ emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) { MAILBOX4 *mb = (MAILBOX4 *)mbq; emlxs_port_t *port = &PPORT; - XRIobj_t *xp; + XRIobj_t *xrip; MATCHMAP *mp; mbox_req_hdr_t *hdr_req; uint32_t i, cnt, xri_cnt; @@ -6291,7 +6065,7 @@ emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand); return (EIO); } - mbq->nonembed = (uint8_t *)mp; + mbq->nonembed = (void *)mp; /* * Signifies a non embedded command @@ -6305,7 +6079,7 @@ emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) (IOCTL_FCOE_CFG_POST_SGL_PAGES *)(hdr_req + 1); - xp = hba->sli.sli4.XRIp; + xrip = hba->sli.sli4.XRIp; cnt = hba->sli.sli4.XRICount; while (cnt) { bzero((void *) hdr_req, mp->size); @@ -6326,18 +6100,18 @@ emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) hdr_req->req_length = size; post_sgl->params.request.xri_count = 0; - post_sgl->params.request.xri_start = xp->XRI; + post_sgl->params.request.xri_start = xrip->XRI; xri_cnt = (size - sizeof (IOCTL_FCOE_CFG_POST_SGL_PAGES)) / sizeof (FCOE_SGL_PAGES); for (i = 0; i < xri_cnt; i++) { post_sgl->params.request.xri_count++; post_sgl->params.request.pages[i].sgl_page0.addrLow = - PADDR_LO(xp->SGList.phys); + PADDR_LO(xrip->SGList.phys); post_sgl->params.request.pages[i].sgl_page0.addrHigh = - PADDR_HI(xp->SGList.phys); + PADDR_HI(xrip->SGList.phys); cnt--; - xp++; + xrip++; if (cnt == 0) { break; } @@ -6350,13 +6124,13 @@ emlxs_sli4_post_sgl_pages(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand, mb->mbxStatus, post_sgl->params.request.xri_count, post_sgl->params.request.xri_start); - (void) emlxs_mem_buf_free(hba, mp); - mbq->nonembed = (uint8_t *)NULL; + emlxs_mem_buf_free(hba, mp); + mbq->nonembed = NULL; return (EIO); } } - (void) emlxs_mem_buf_free(hba, mp); - mbq->nonembed = (uint8_t *)NULL; + emlxs_mem_buf_free(hba, mp); + mbq->nonembed = NULL; return (0); } /* emlxs_sli4_post_sgl_pages() */ @@ -6414,7 +6188,7 @@ emlxs_sli4_post_hdr_tmplates(emlxs_hba_t *hba, MAILBOXQ *mbq) mb->mbxCommand, mb->mbxStatus); return (EIO); } -emlxs_data_dump(hba, "POST_HDR", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "POST_HDR", (uint32_t *)mb, 18, 0); return (0); } /* emlxs_sli4_post_hdr_tmplates() */ @@ -6431,10 +6205,11 @@ emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq) IOCTL_FCOE_WQ_CREATE *wq; IOCTL_FCOE_RQ_CREATE *rq; IOCTL_COMMON_MQ_CREATE *mq; + IOCTL_COMMON_MCC_CREATE_EXT *mcc_ext; emlxs_rqdbu_t rqdb; - int i, j; - int num_cq, total_cq; - int num_wq, total_wq; + uint16_t i, j; + uint16_t num_cq, total_cq; + uint16_t num_wq, total_wq; /* * The first CQ is reserved for ASYNC events, @@ -6474,7 +6249,7 @@ emlxs_sli4_create_queues(emlxs_hba_t *hba, MAILBOXQ *mbq) hba->sli.sli4.eq_map[eq->params.response.EQId] = i; hba->sli.sli4.eq[i].lastwq = total_wq; -emlxs_data_dump(hba, "EQ0_CREATE", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "EQ0_CREATE", (uint32_t *)mb, 18, 0); num_wq = cfg[CFG_NUM_WQ].current; num_cq = num_wq; if (i == 0) { @@ -6526,7 +6301,7 @@ emlxs_data_dump(hba, "EQ0_CREATE", (uint32_t *)mb, 18, 0); &hba->chan[total_cq - EMLXS_CQ_OFFSET_WQ]; break; } -emlxs_data_dump(hba, "CQX_CREATE", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "CQX_CREATE", (uint32_t *)mb, 18, 0); total_cq++; } @@ -6555,9 +6330,10 @@ emlxs_data_dump(hba, "CQX_CREATE", (uint32_t *)mb, 18, 0); hba->sli.sli4.wq[total_wq].cqid = hba->sli.sli4.cq[total_wq+EMLXS_CQ_OFFSET_WQ].qid; -emlxs_data_dump(hba, "WQ_CREATE", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "WQ_CREATE", (uint32_t *)mb, 18, 0); total_wq++; } + hba->last_msiid = i; } /* We assume 1 RQ pair will handle ALL incoming data */ @@ -6591,7 +6367,7 @@ emlxs_data_dump(hba, "WQ_CREATE", (uint32_t *)mb, 18, 0); rq = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload; hba->sli.sli4.rq[i].qid = rq->params.response.RQId; hba->sli.sli4.rq_map[rq->params.response.RQId] = i; -emlxs_data_dump(hba, "RQ CREATE", (uint32_t *)mb, 18, 0); +emlxs_data_dump(port, "RQ CREATE", (uint32_t *)mb, 18, 0); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "RQ CREATE: rq[%d].qid=%d cqid=%d", @@ -6624,82 +6400,35 @@ emlxs_data_dump(hba, "RQ CREATE", (uint32_t *)mb, 18, 0); /* Reuse mbq from previous mbox */ bzero(mbq, sizeof (MAILBOXQ)); - emlxs_mb_mq_create(hba, mbq); + emlxs_mb_mcc_create_ext(hba, mbq); if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to Create MQ %d: Mailbox cmd=%x status=%x ", + "Unable to Create MCC_EXT %d: Mailbox cmd=%x status=%x ", i, mb->mbxCommand, mb->mbxStatus); - return (EIO); - } - mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload; - hba->sli.sli4.mq.qid = mq->params.response.MQId; - return (0); - -} /* emlxs_sli4_create_queues() */ + /* Reuse mbq from previous mbox */ + bzero(mbq, sizeof (MAILBOXQ)); -static int -emlxs_fcf_bind(emlxs_hba_t *hba) -{ - MAILBOXQ *mbq; - int rc; - - if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { - return (0); - } - if (!(hba->flag & FC_FIP_SUPPORTED)) { - /* - * If the firmware donesn't support FIP, we must - * build the fcf table manually first. - */ - rc = emlxs_mbext_add_fcf_table(hba, mbq, 0); - } else { - rc = emlxs_mbext_read_fcf_table(hba, mbq, -1); - } + emlxs_mb_mq_create(hba, mbq); + if (emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != + MBX_SUCCESS) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, + "Unable to Create MQ %d: Mailbox cmd=%x status=%x ", + i, mb->mbxCommand, mb->mbxStatus); + return (EIO); + } - if (rc == 0) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + mq = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload; + hba->sli.sli4.mq.qid = mq->params.response.MQId; return (0); } - rc = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); - if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); - } - return (1); - -} /* emlxs_fcf_bind() */ - - -static int -emlxs_fcf_unbind(emlxs_hba_t *hba, uint32_t index) -{ - FCFIobj_t *fp; - int i; - - mutex_enter(&hba->sli.sli4.id_lock); - /* Loop thru all FCFIs */ - fp = hba->sli.sli4.FCFIp; - for (i = 0; i < hba->sli.sli4.FCFICount; i++) { - if ((index == MAX_FCFCONNECTLIST_ENTRIES) || - (index == fp->FCF_index)) { - if (fp->state & RESOURCE_ALLOCATED) { - mutex_exit(&hba->sli.sli4.id_lock); - if (hba->state > FC_LINK_DOWN) { - fp->state &= ~RESOURCE_FCFI_DISC; - /* Declare link down here */ - emlxs_linkdown(hba); - } - /* There should only be 1 FCF for now */ - return (1); - } - } - } - mutex_exit(&hba->sli.sli4.id_lock); + mcc_ext = (IOCTL_COMMON_MCC_CREATE_EXT *)&mb->un.varSLIConfig.payload; + hba->sli.sli4.mq.qid = mcc_ext->params.response.id; return (0); -} /* emlxs_fcf_unbind() */ +} /* emlxs_sli4_create_queues() */ /*ARGSUSED*/ @@ -6707,7 +6436,6 @@ extern int emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec) { int i; - uint32_t rval = 1; if (!(hba->flag & FC_FIP_SUPPORTED)) { if (!hba->sli.sli4.cfgFCOE.length) { @@ -6737,174 +6465,14 @@ emlxs_sli4_check_fcf_config(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec) /* Just check FabricName for now */ for (i = 0; i < MAX_FCFCONNECTLIST_ENTRIES; i++) { if ((hba->sli.sli4.cfgFCF.entry[i].FabricNameValid) && - (hba->sli.sli4.cfgFCF.entry[i].Valid)) { - rval = 0; - if (bcmp((char *)fcfrec->fabric_name_identifier, - hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0) { - return (1); /* success */ - } - } - } - return (rval); -} - - -extern FCFIobj_t * -emlxs_sli4_assign_fcfi(emlxs_hba_t *hba, FCF_RECORD_t *fcfrec) -{ - emlxs_port_t *port = &PPORT; - FCFIobj_t *fcfp; - int i; - - fcfp = emlxs_sli4_find_fcfi_fcfrec(hba, fcfrec); - if (!fcfp) { - fcfp = emlxs_sli4_alloc_fcfi(hba); - if (!fcfp) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to alloc FCFI for fcf index %d", - fcfrec->fcf_index); - return (0); - } - fcfp->FCF_index = fcfrec->fcf_index; - } - - bcopy((char *)fcfrec, &fcfp->fcf_rec, sizeof (FCF_RECORD_t)); - - for (i = 0; i < 512; i++) { - if (fcfrec->vlan_bitmap[i / 8] == (1 << (i % 8))) { - fcfp->vlan_id = i; - fcfp->state |= RESOURCE_FCFI_VLAN_ID; - break; - } - } - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "FCFI %d: idx %x av %x val %x ste %x macp %x vid %x " - "addr: %02x:%02x:%02x:%02x:%02x:%02x", - fcfp->FCFI, - fcfrec->fcf_index, - fcfrec->fcf_available, - fcfrec->fcf_valid, - fcfrec->fcf_state, - fcfrec->mac_address_provider, - fcfp->vlan_id, - fcfrec->fcf_mac_address_hi[0], - fcfrec->fcf_mac_address_hi[1], - fcfrec->fcf_mac_address_hi[2], - fcfrec->fcf_mac_address_hi[3], - fcfrec->fcf_mac_address_low[0], - fcfrec->fcf_mac_address_low[1]); - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "fabric: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - fcfrec->fabric_name_identifier[0], - fcfrec->fabric_name_identifier[1], - fcfrec->fabric_name_identifier[2], - fcfrec->fabric_name_identifier[3], - fcfrec->fabric_name_identifier[4], - fcfrec->fabric_name_identifier[5], - fcfrec->fabric_name_identifier[6], - fcfrec->fabric_name_identifier[7]); - - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "switch: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - fcfrec->switch_name_identifier[0], - fcfrec->switch_name_identifier[1], - fcfrec->switch_name_identifier[2], - fcfrec->switch_name_identifier[3], - fcfrec->switch_name_identifier[4], - fcfrec->switch_name_identifier[5], - fcfrec->switch_name_identifier[6], - fcfrec->switch_name_identifier[7]); - - return (fcfp); - -} /* emlxs_sli4_assign_fcfi() */ - - -extern FCFIobj_t * -emlxs_sli4_bind_fcfi(emlxs_hba_t *hba) -{ - emlxs_port_t *port = &PPORT; - FCFIobj_t *fp; - VFIobj_t *vfip; - MAILBOXQ *mbq; - int rc; - uint32_t i; - - mutex_enter(&hba->sli.sli4.id_lock); - /* Loop thru all FCFIs */ - fp = hba->sli.sli4.FCFIp; - for (i = 0; i < hba->sli.sli4.FCFICount; i++) { - if (fp->state & RESOURCE_ALLOCATED) { - /* - * Look for one thats valid, available - * and matches our FCF configuration info. - */ - if (fp->fcf_rec.fcf_valid && - fp->fcf_rec.fcf_available && - emlxs_sli4_check_fcf_config(hba, &fp->fcf_rec)) { - /* Since we only support one FCF */ - break; - } - } - fp++; - } - mutex_exit(&hba->sli.sli4.id_lock); - - if (i == hba->sli.sli4.FCFICount) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, - "Not a valid FCF"); - return (0); - } - - if (fp->state & RESOURCE_FCFI_REG) { - - if (!fp->fcf_vfi) { - vfip = emlxs_sli4_alloc_vfi(hba, fp); - if (!vfip) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Fabric VFI alloc failure, fcf index %d", - fp->FCF_index); - (void) emlxs_sli4_free_fcfi(hba, fp); - return (0); - } - fp->fcf_vfi = vfip; - } - - if (!fp->fcf_vpi) { - fp->fcf_vpi = port; - port->VFIp = fp->fcf_vfi; - port->VFIp->outstandingVPIs++; - } - - if (!(fp->state & RESOURCE_FCFI_DISC)) { - fp->state |= RESOURCE_FCFI_DISC; - emlxs_linkup(hba); + (bcmp((char *)fcfrec->fabric_name_identifier, + hba->sli.sli4.cfgFCF.entry[i].FabricName, 8) == 0)) { + return (1); /* success */ } - return (fp); - } - - if ((mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to alloc mbox for fcf index %d", - fp->fcf_rec.fcf_index); - return (0); - } - emlxs_mb_reg_fcfi(hba, mbq, fp); - - rc = emlxs_sli4_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); - if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to issue mbox for fcf index %d", - fp->fcf_rec.fcf_index); - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); } + return (0); - return (fp); - -} /* emlxs_sli4_bind_fcfi() */ +} /* emlxs_sli4_check_fcf_config() */ extern void @@ -6912,6 +6480,8 @@ emlxs_sli4_timer(emlxs_hba_t *hba) { /* Perform SLI4 level timer checks */ + emlxs_fcf_timer_notify(hba); + emlxs_sli4_timer_check_mbox(hba); return; @@ -6937,6 +6507,8 @@ emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba) mutex_exit(&EMLXS_PORT_LOCK); return; } + + /* The first to service the mbox queue will clear the timer */ hba->mbox_timer = 0; if (hba->mbox_queue_flag) { @@ -6988,7 +6560,7 @@ emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba) emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); /* Trigger adapter shutdown */ - emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); + emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0); return; @@ -6996,9 +6568,8 @@ emlxs_sli4_timer_check_mbox(emlxs_hba_t *hba) extern void -emlxs_data_dump(emlxs_hba_t *hba, char *str, uint32_t *iptr, int cnt, int err) +emlxs_data_dump(emlxs_port_t *port, char *str, uint32_t *iptr, int cnt, int err) { - emlxs_port_t *port = &PPORT; void *msg; if (err) { @@ -7076,7 +6647,7 @@ emlxs_ue_dump(emlxs_hba_t *hba, char *str) } /* emlxs_ue_dump() */ -void +static void emlxs_sli4_poll_erratt(emlxs_hba_t *hba) { emlxs_port_t *port = &PPORT; @@ -7093,7 +6664,8 @@ emlxs_sli4_poll_erratt(emlxs_hba_t *hba) (uint32_t *)(hba->pci_addr + PCICFG_UE_STATUS_HI_OFFSET)); if ((~hba->sli.sli4.ue_mask_lo & ue_l) || - (~hba->sli.sli4.ue_mask_hi & ue_h)) { + (~hba->sli.sli4.ue_mask_hi & ue_h) || + (hba->sli.sli4.flag & EMLXS_SLI4_HW_ERROR)) { /* Unrecoverable error detected */ /* Shut the HBA down */ EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, @@ -7106,37 +6678,162 @@ emlxs_sli4_poll_erratt(emlxs_hba_t *hba) emlxs_sli4_hba_flush_chipq(hba); - emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); + emlxs_thread_spawn(hba, emlxs_shutdown_thread, 0, 0); } } /* emlxs_sli4_poll_erratt() */ -int -emlxs_sli4_unreg_all_rpi_by_port(emlxs_port_t *port) + +extern uint32_t +emlxs_sli4_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, + emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) { emlxs_hba_t *hba = HBA; + NODELIST *node; + RPIobj_t *rpip; + uint32_t rval; + + /* Check for invalid node ids to register */ + if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { + return (1); + } + + if (did & 0xff000000) { + return (1); + } + + if ((rval = emlxs_mb_check_sparm(hba, param))) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, + "Invalid service parameters. did=%06x rval=%d", did, + rval); + + return (1); + } + + /* Check if the node limit has been reached */ + if (port->node_count >= hba->max_nodes) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, + "Limit reached. did=%06x count=%d", did, + port->node_count); + + return (1); + } + + node = emlxs_node_find_did(port, did); + rpip = EMLXS_NODE_TO_RPI(port, node); + + rval = emlxs_rpi_online_notify(port, rpip, did, param, (void *)sbp, + (void *)ubp, (void *)iocbq); + + return (rval); + +} /* emlxs_sli4_reg_did() */ + + +extern uint32_t +emlxs_sli4_unreg_node(emlxs_port_t *port, emlxs_node_t *node, + emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) +{ + RPIobj_t *rpip; + uint32_t rval; + + if (!node) { + /* Unreg all nodes */ + (void) emlxs_sli4_unreg_all_nodes(port); + return (1); + } + + /* Check for base node */ + if (node == &port->node_base) { + /* Just flush base node */ + (void) emlxs_tx_node_flush(port, &port->node_base, + 0, 0, 0); + + (void) emlxs_chipq_node_flush(port, 0, + &port->node_base, 0); + + port->did = 0; + + /* Return now */ + return (1); + } + + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, + "unreg_node:%p did=%x rpi=%d", + node, node->nlp_DID, node->nlp_Rpi); + + rpip = EMLXS_NODE_TO_RPI(port, node); + + if (!rpip) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, + "unreg_node:%p did=%x rpi=%d. RPI not found.", + node, node->nlp_DID, node->nlp_Rpi); + + emlxs_node_rm(port, node); + return (1); + } + + rval = emlxs_rpi_offline_notify(port, rpip, (void *)sbp, (void *)ubp, + (void *)iocbq); + + return (rval); + +} /* emlxs_sli4_unreg_node() */ + + +extern uint32_t +emlxs_sli4_unreg_all_nodes(emlxs_port_t *port) +{ NODELIST *nlp; int i; + uint32_t found; - rw_enter(&port->node_rwlock, RW_WRITER); + /* Set the node tags */ + /* We will process all nodes with this tag */ + rw_enter(&port->node_rwlock, RW_READER); + found = 0; for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { nlp = port->node_table[i]; while (nlp != NULL) { - if (nlp->nlp_Rpi != 0xffff) { - rw_exit(&port->node_rwlock); - (void) emlxs_mb_unreg_rpi(port, - nlp->nlp_Rpi, 0, 0, 0); - rw_enter(&port->node_rwlock, RW_WRITER); - } else { - /* Just free nlp back to the pool */ - port->node_table[i] = nlp->nlp_list_next; - (void) emlxs_mem_put(hba, MEM_NLP, - (uint8_t *)nlp); - } - nlp = port->node_table[i]; + found = 1; + nlp->nlp_tag = 1; + nlp = nlp->nlp_list_next; } } rw_exit(&port->node_rwlock); + if (!found) { + return (0); + } + + for (;;) { + rw_enter(&port->node_rwlock, RW_READER); + found = 0; + for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { + nlp = port->node_table[i]; + while (nlp != NULL) { + if (!nlp->nlp_tag) { + nlp = nlp->nlp_list_next; + continue; + } + nlp->nlp_tag = 0; + found = 1; + break; + } + + if (found) { + break; + } + } + rw_exit(&port->node_rwlock); + + if (!found) { + break; + } + + (void) emlxs_sli4_unreg_node(port, nlp, 0, 0, 0); + } + return (0); -} /* emlxs_sli4_unreg_all_rpi_by_port() */ + +} /* emlxs_sli4_unreg_all_nodes() */ diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c index 695bf6a712..50747c9ce4 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c @@ -47,10 +47,10 @@ static int32_t emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp); static void emlxs_fca_attach(emlxs_hba_t *hba); static void emlxs_fca_detach(emlxs_hba_t *hba); static void emlxs_drv_banner(emlxs_hba_t *hba); -static int32_t emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd); static int32_t emlxs_get_props(emlxs_hba_t *hba); -static int32_t emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp); +static int32_t emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp, + uint32_t *pkt_flags); static int32_t emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp); static int32_t emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp); static int32_t emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp); @@ -69,10 +69,17 @@ static uint32_t emlxs_integrity_check(emlxs_hba_t *hba); static uint32_t emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args, uint32_t *arg); +#if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) static void emlxs_read_vport_prop(emlxs_hba_t *hba); +#endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */ +extern int +emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id); +extern int +emlxs_select_msiid(emlxs_hba_t *hba); + /* * Driver Entry Routines. */ @@ -88,19 +95,19 @@ static int32_t emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **); /* * FC_AL Transport Functions. */ -static opaque_t emlxs_bind_port(dev_info_t *, fc_fca_port_info_t *, +static opaque_t emlxs_fca_bind_port(dev_info_t *, fc_fca_port_info_t *, fc_fca_bind_info_t *); -static void emlxs_unbind_port(opaque_t); +static void emlxs_fca_unbind_port(opaque_t); static void emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *); -static int32_t emlxs_get_cap(opaque_t, char *, void *); -static int32_t emlxs_set_cap(opaque_t, char *, void *); -static int32_t emlxs_get_map(opaque_t, fc_lilpmap_t *); -static int32_t emlxs_ub_alloc(opaque_t, uint64_t *, uint32_t, +static int32_t emlxs_fca_get_cap(opaque_t, char *, void *); +static int32_t emlxs_fca_set_cap(opaque_t, char *, void *); +static int32_t emlxs_fca_get_map(opaque_t, fc_lilpmap_t *); +static int32_t emlxs_fca_ub_alloc(opaque_t, uint64_t *, uint32_t, uint32_t *, uint32_t); -static int32_t emlxs_ub_free(opaque_t, uint32_t, uint64_t *); +static int32_t emlxs_fca_ub_free(opaque_t, uint32_t, uint64_t *); -static opaque_t emlxs_get_device(opaque_t, fc_portid_t); -static int32_t emlxs_notify(opaque_t, uint32_t); +static opaque_t emlxs_fca_get_device(opaque_t, fc_portid_t); +static int32_t emlxs_fca_notify(opaque_t, uint32_t); static void emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *); /* @@ -120,8 +127,6 @@ static int32_t emlxs_hba_detach(dev_info_t *); static int32_t emlxs_hba_attach(dev_info_t *); static void emlxs_lock_destroy(emlxs_hba_t *); static void emlxs_lock_init(emlxs_hba_t *); -static ULP_BDE64 *emlxs_pkt_to_bpl(ULP_BDE64 *, fc_packet_t *, - uint32_t, uint8_t); char *emlxs_pm_components[] = { "NAME=emlxx000", @@ -257,23 +262,23 @@ ddi_device_acc_attr_t emlxs_data_acc_attr = { &emlxs_data_acc_attr, /* fca access atributes */ 0, /* fca_num_npivports */ {0, 0, 0, 0, 0, 0, 0, 0}, /* Physical port WWPN */ - emlxs_bind_port, - emlxs_unbind_port, - emlxs_pkt_init, - emlxs_pkt_uninit, - emlxs_transport, - emlxs_get_cap, - emlxs_set_cap, - emlxs_get_map, - emlxs_transport, - emlxs_ub_alloc, - emlxs_ub_free, - emlxs_ub_release, - emlxs_pkt_abort, + emlxs_fca_bind_port, + emlxs_fca_unbind_port, + emlxs_fca_pkt_init, + emlxs_fca_pkt_uninit, + emlxs_fca_transport, + emlxs_fca_get_cap, + emlxs_fca_set_cap, + emlxs_fca_get_map, + emlxs_fca_transport, + emlxs_fca_ub_alloc, + emlxs_fca_ub_free, + emlxs_fca_ub_release, + emlxs_fca_pkt_abort, emlxs_fca_reset, - emlxs_port_manage, - emlxs_get_device, - emlxs_notify + emlxs_fca_port_manage, + emlxs_fca_get_device, + emlxs_fca_notify }; #endif /* EMLXS_MODREV5 */ @@ -295,23 +300,23 @@ static fc_fca_tran_t emlxs_fca_tran = { &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ &emlxs_data_acc_attr, /* fca access atributes */ - emlxs_bind_port, - emlxs_unbind_port, - emlxs_pkt_init, - emlxs_pkt_uninit, - emlxs_transport, - emlxs_get_cap, - emlxs_set_cap, - emlxs_get_map, - emlxs_transport, - emlxs_ub_alloc, - emlxs_ub_free, - emlxs_ub_release, - emlxs_pkt_abort, + emlxs_fca_bind_port, + emlxs_fca_unbind_port, + emlxs_fca_pkt_init, + emlxs_fca_pkt_uninit, + emlxs_fca_transport, + emlxs_fca_get_cap, + emlxs_fca_set_cap, + emlxs_fca_get_map, + emlxs_fca_transport, + emlxs_fca_ub_alloc, + emlxs_fca_ub_free, + emlxs_fca_ub_release, + emlxs_fca_pkt_abort, emlxs_fca_reset, - emlxs_port_manage, - emlxs_get_device, - emlxs_notify + emlxs_fca_port_manage, + emlxs_fca_get_device, + emlxs_fca_notify }; #endif /* EMLXS_MODEREV4 */ @@ -333,23 +338,23 @@ static fc_fca_tran_t emlxs_fca_tran = { &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ &emlxs_data_acc_attr, /* fca access atributes */ - emlxs_bind_port, - emlxs_unbind_port, - emlxs_pkt_init, - emlxs_pkt_uninit, - emlxs_transport, - emlxs_get_cap, - emlxs_set_cap, - emlxs_get_map, - emlxs_transport, - emlxs_ub_alloc, - emlxs_ub_free, - emlxs_ub_release, - emlxs_pkt_abort, + emlxs_fca_bind_port, + emlxs_fca_unbind_port, + emlxs_fca_pkt_init, + emlxs_fca_pkt_uninit, + emlxs_fca_transport, + emlxs_fca_get_cap, + emlxs_fca_set_cap, + emlxs_fca_get_map, + emlxs_fca_transport, + emlxs_fca_ub_alloc, + emlxs_fca_ub_free, + emlxs_fca_ub_release, + emlxs_fca_pkt_abort, emlxs_fca_reset, - emlxs_port_manage, - emlxs_get_device, - emlxs_notify + emlxs_fca_port_manage, + emlxs_fca_get_device, + emlxs_fca_notify }; #endif /* EMLXS_MODREV3 */ @@ -364,23 +369,23 @@ static fc_fca_tran_t emlxs_fca_tran = { 0, /* iblock, to be filled in later */ &emlxs_dma_attr, /* dma attributes */ &emlxs_data_acc_attr, /* access atributes */ - emlxs_bind_port, - emlxs_unbind_port, - emlxs_pkt_init, - emlxs_pkt_uninit, - emlxs_transport, - emlxs_get_cap, - emlxs_set_cap, - emlxs_get_map, - emlxs_transport, - emlxs_ub_alloc, - emlxs_ub_free, - emlxs_ub_release, - emlxs_pkt_abort, + emlxs_fca_bind_port, + emlxs_fca_unbind_port, + emlxs_fca_pkt_init, + emlxs_fca_pkt_uninit, + emlxs_fca_transport, + emlxs_fca_get_cap, + emlxs_fca_set_cap, + emlxs_fca_get_map, + emlxs_fca_transport, + emlxs_fca_ub_alloc, + emlxs_fca_ub_free, + emlxs_fca_ub_release, + emlxs_fca_pkt_abort, emlxs_fca_reset, - emlxs_port_manage, - emlxs_get_device, - emlxs_notify + emlxs_fca_port_manage, + emlxs_fca_get_device, + emlxs_fca_notify }; #endif /* EMLXS_MODREV2 */ @@ -400,6 +405,8 @@ emlxs_device_t emlxs_device; uint32_t emlxs_instance[MAX_FC_BRDS]; /* uses emlxs_device.lock */ uint32_t emlxs_instance_count = 0; /* uses emlxs_device.lock */ +uint32_t emlxs_instance_flag = 0; /* uses emlxs_device.lock */ +#define EMLXS_FW_SHOW 0x00000001 /* @@ -943,6 +950,7 @@ emlxs_table_t emlxs_elscmd_table[] = { {ELS_CMD_ECHO, "ECHO"}, {ELS_CMD_TEST, "TEST"}, {ELS_CMD_RRQ, "RRQ"}, + {ELS_CMD_REC, "REC"}, {ELS_CMD_PRLI, "PRLI"}, {ELS_CMD_PRLO, "PRLO"}, {ELS_CMD_SCN, "SCN"}, @@ -1409,44 +1417,34 @@ emlxs_port_init(emlxs_port_t *port) void emlxs_disable_pcie_ce_err(emlxs_hba_t *hba) { -#define NXT_PTR_OFF PCI_BYTE -#define PCIE_DEVCTL_OFF 0x8 -#define PCIE_CAP_ID 0x10 - - uint8_t cap_ptr; - uint8_t cap_id; - uint16_t tmp16; - - cap_ptr = ddi_get8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + PCI_CAP_POINTER)); + uint16_t reg; - while (cap_ptr) { - cap_id = ddi_get8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + cap_ptr)); - - if (cap_id == PCIE_CAP_ID) { - break; - } - cap_ptr = ddi_get8(hba->pci_acc_handle, - (uint8_t *)(hba->pci_addr + cap_ptr + NXT_PTR_OFF)); + if (!hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) { + return; } - /* PCI Express Capability Register Set */ /* Turn off the Correctable Error Reporting */ /* (the Device Control Register, bit 0). */ + reg = ddi_get16(hba->pci_acc_handle, + (uint16_t *)(hba->pci_addr + + hba->pci_cap_offset[PCI_CAP_ID_PCI_E] + + PCIE_DEVCTL_OFFSET)); + + reg &= ~1; + + (void) ddi_put16(hba->pci_acc_handle, + (uint16_t *)(hba->pci_addr + + hba->pci_cap_offset[PCI_CAP_ID_PCI_E] + + PCIE_DEVCTL_OFFSET), + reg); + + return; + +} /* emlxs_disable_pcie_ce_err() */ - if (cap_id == PCIE_CAP_ID) { - tmp16 = ddi_get16(hba->pci_acc_handle, - (uint16_t *)(hba->pci_addr + cap_ptr + PCIE_DEVCTL_OFF)); - tmp16 &= ~1; - (void) ddi_put16(hba->pci_acc_handle, - (uint16_t *)(hba->pci_addr + cap_ptr + PCIE_DEVCTL_OFF), - tmp16); - } -} /* - * emlxs_bind_port + * emlxs_fca_bind_port * * Arguments: * @@ -1458,7 +1456,7 @@ emlxs_disable_pcie_ce_err(emlxs_hba_t *hba) * */ static opaque_t -emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, +emlxs_fca_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, fc_fca_bind_info_t *bind_info) { emlxs_hba_t *hba; @@ -1495,7 +1493,7 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, #endif { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "emlxs_port_bind: Port %d not supported.", + "fca_bind_port: Port %d not supported.", bind_info->port_num); mutex_exit(&EMLXS_PORT_LOCK); @@ -1510,7 +1508,7 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, if (port->tgt_mode) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "emlxs_port_bind: Port %d is in target mode.", + "fca_bind_port: Port %d is in target mode.", bind_info->port_num); mutex_exit(&EMLXS_PORT_LOCK); @@ -1521,7 +1519,7 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, if (!port->ini_mode) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "emlxs_port_bind: Port %d is not in initiator mode.", + "fca_bind_port: Port %d is not in initiator mode.", bind_info->port_num); mutex_exit(&EMLXS_PORT_LOCK); @@ -1534,7 +1532,7 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, if (port->flag & EMLXS_PORT_BOUND) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "emlxs_port_bind: Port %d already bound. flag=%x", + "fca_bind_port: Port %d already bound. flag=%x", bind_info->port_num, port->flag); mutex_exit(&EMLXS_PORT_LOCK); @@ -1592,6 +1590,10 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, !(hba->flag & FC_NPIV_SUPPORTED)))) { port_info->pi_port_state = FC_STATE_OFFLINE; port_info->pi_topology = FC_TOP_UNKNOWN; + } else if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && + (port->VPIobj.state == VPI_STATE_OFFLINE)) { + port_info->pi_port_state = FC_STATE_OFFLINE; + port_info->pi_topology = FC_TOP_UNKNOWN; } #ifdef MENLO_SUPPORT else if (hba->flag & FC_MENLO_MODE) { @@ -1665,7 +1667,8 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, } /* PCIE Correctable Error Reporting workaround */ - if ((hba->model_info.chip == EMLXS_BE_CHIP) && + if (((hba->model_info.chip == EMLXS_BE2_CHIP) || + (hba->model_info.chip == EMLXS_BE3_CHIP)) && (bind_info->port_num == 0)) { emlxs_disable_pcie_ce_err(hba); } @@ -1803,7 +1806,7 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, #endif /* >= EMLXS_MODREV5 */ -#if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLX_MODREV == EMLXS_MODREV4)) +#if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLXS_MODREV == EMLXS_MODREV4)) port_info->pi_rnid_params.params.num_attached = 0; @@ -2041,13 +2044,17 @@ emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, mutex_exit(&EMLXS_PORT_LOCK); + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_vpi_port_bind_notify(port); + } + return ((opaque_t)port); -} /* emlxs_bind_port() */ +} /* emlxs_fca_bind_port() */ static void -emlxs_unbind_port(opaque_t fca_port_handle) +emlxs_fca_unbind_port(opaque_t fca_port_handle) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -2055,17 +2062,18 @@ emlxs_unbind_port(opaque_t fca_port_handle) EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_unbind_port: port=%p", port); + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + (void) emlxs_vpi_port_unbind_notify(port, 1); + } + /* Destroy & flush all port nodes, if they exist */ if (port->node_count) { - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - (void) emlxs_sli4_unreg_all_rpi_by_port(port); - } else { - (void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 0); - } + (void) emlxs_mb_unreg_node(port, 0, 0, 0, 0); } #if (EMLXS_MODREV >= EMLXS_MODREV5) - if ((hba->flag & FC_NPIV_ENABLED) && + if ((hba->sli_mode <= EMLXS_HBA_SLI3_MODE) && + (hba->flag & FC_NPIV_ENABLED) && (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE))) { (void) emlxs_mb_unreg_vpi(port); } @@ -2090,12 +2098,12 @@ emlxs_unbind_port(opaque_t fca_port_handle) return; -} /* emlxs_unbind_port() */ +} /* emlxs_fca_unbind_port() */ /*ARGSUSED*/ extern int -emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) +emlxs_fca_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -2106,7 +2114,7 @@ emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) } bzero((void *)sbp, sizeof (emlxs_buf_t)); - mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg); + mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg)); sbp->pkt_flags = PACKET_VALID | PACKET_ULP_OWNED; sbp->port = port; @@ -2115,7 +2123,7 @@ emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) return (FC_SUCCESS); -} /* emlxs_pkt_init() */ +} /* emlxs_fca_pkt_init() */ @@ -2144,7 +2152,7 @@ emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp) if (!port->tgt_mode) { sbp->node = NULL; sbp->did = 0; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = 0; sbp->class = 0; sbp->channel = NULL; @@ -2200,7 +2208,7 @@ emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp) */ /*ARGSUSED*/ extern int -emlxs_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt) +emlxs_fca_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt) { emlxs_buf_t *sbp = PKT2PRIV(pkt); @@ -2216,11 +2224,11 @@ emlxs_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt) return (FC_SUCCESS); -} /* emlxs_pkt_uninit() */ +} /* emlxs_fca_pkt_uninit() */ static int -emlxs_get_cap(opaque_t fca_port_handle, char *cap, void *ptr) +emlxs_fca_get_cap(opaque_t fca_port_handle, char *cap, void *ptr) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -2318,12 +2326,12 @@ emlxs_get_cap(opaque_t fca_port_handle, char *cap, void *ptr) return (rval); -} /* emlxs_get_cap() */ +} /* emlxs_fca_get_cap() */ static int -emlxs_set_cap(opaque_t fca_port_handle, char *cap, void *ptr) +emlxs_fca_set_cap(opaque_t fca_port_handle, char *cap, void *ptr) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; @@ -2332,11 +2340,11 @@ emlxs_set_cap(opaque_t fca_port_handle, char *cap, void *ptr) return (FC_CAP_ERROR); -} /* emlxs_set_cap() */ +} /* emlxs_fca_set_cap() */ static opaque_t -emlxs_get_device(opaque_t fca_port_handle, fc_portid_t d_id) +emlxs_fca_get_device(opaque_t fca_port_handle, fc_portid_t d_id) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; @@ -2345,11 +2353,11 @@ emlxs_get_device(opaque_t fca_port_handle, fc_portid_t d_id) return (NULL); -} /* emlxs_get_device() */ +} /* emlxs_fca_get_device() */ static int32_t -emlxs_notify(opaque_t fca_port_handle, uint32_t cmd) +emlxs_fca_notify(opaque_t fca_port_handle, uint32_t cmd) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; @@ -2358,12 +2366,12 @@ emlxs_notify(opaque_t fca_port_handle, uint32_t cmd) return (FC_SUCCESS); -} /* emlxs_notify */ +} /* emlxs_fca_notify */ static int -emlxs_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf) +emlxs_fca_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -2410,12 +2418,12 @@ emlxs_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf) return (FC_SUCCESS); -} /* emlxs_get_map() */ +} /* emlxs_fca_get_map() */ extern int -emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt) +emlxs_fca_transport(opaque_t fca_port_handle, fc_packet_t *pkt) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -2480,7 +2488,7 @@ emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt) switch (pkt->pkt_tran_type) { case FC_PKT_FCP_READ: case FC_PKT_FCP_WRITE: - rval = emlxs_send_fcp_cmd(port, sbp); + rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags); break; case FC_PKT_IP_WRITE: @@ -2491,7 +2499,7 @@ emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt) case FC_PKT_EXCHANGE: switch (pkt->pkt_cmd_fhdr.type) { case FC_TYPE_SCSI_FCP: - rval = emlxs_send_fcp_cmd(port, sbp); + rval = emlxs_send_fcp_cmd(port, sbp, &pkt_flags); break; case FC_TYPE_FC_SERVICES: @@ -2562,7 +2570,7 @@ emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt) return (FC_SUCCESS); -} /* emlxs_transport() */ +} /* emlxs_fca_transport() */ @@ -2773,7 +2781,7 @@ done: static int -emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, +emlxs_fca_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, uint32_t *count, uint32_t type) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; @@ -2800,19 +2808,19 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, if (!(port->flag & EMLXS_PORT_BOUND)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_alloc failed: Port not bound! size=%x count=%d " + "fca_ub_alloc failed: Port not bound! size=%x count=%d " "type=%x", size, *count, type); return (FC_FAILURE); } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_alloc: size=%x count=%d type=%x", size, *count, type); + "fca_ub_alloc: size=%x count=%d type=%x", size, *count, type); if (count && (*count > EMLXS_MAX_UBUFS)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, - "ub_alloc failed: Too many unsolicted buffers requested. " - "count=%x", *count); + "fca_ub_alloc failed: Too many unsolicted buffers " + "requested. count=%x", *count); return (FC_FAILURE); @@ -2820,7 +2828,7 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, if (tokens == NULL) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, - "ub_alloc failed: Token array is NULL."); + "fca_ub_alloc failed: Token array is NULL."); return (FC_FAILURE); } @@ -2847,7 +2855,7 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, if (cfg[CFG_NETWORK_ON].current == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_alloc failed: IP support is disabled."); + "fca_ub_alloc failed: IP support is disabled."); return (FC_FAILURE); } @@ -2885,7 +2893,7 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, pool = port->ub_pool; /* - * The emlxs_ub_alloc() can be called more than once with different + * The emlxs_fca_ub_alloc() can be called more than once with different * size. We will reject the call if there are * duplicate size with the same FC-4 type. */ @@ -2893,8 +2901,9 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, if ((pool->pool_type == type) && (pool->pool_buf_size == size)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, - "ub_alloc failed: Unsolicited buffer pool for %s " - "of size 0x%x bytes already exists.", err, size); + "fca_ub_alloc failed: Unsolicited buffer pool " + "for %s of size 0x%x bytes already exists.", + err, size); result = FC_FAILURE; goto fail; @@ -2949,9 +2958,6 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, /* Allocate the actual buffer */ ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP); - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, - "ub_alloc: buffer=%p token=%x size=%x type=%x ", ubp, - ub_priv->token, ubp->ub_bufsize, type); tokens[i] = (uint64_t)((unsigned long)ubp); port->ub_count++; @@ -2980,8 +2986,7 @@ emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbox); } } port->flag |= EMLXS_PORT_IP_UP; @@ -3008,7 +3013,7 @@ fail: ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, - "ub_alloc failed: Freed buffer=%p token=%x size=%x " + "fca_ub_alloc failed: Freed buffer=%p token=%x size=%x " "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type); /* Free the actual buffer */ @@ -3032,7 +3037,7 @@ fail: return (result); -} /* emlxs_ub_alloc() */ +} /* emlxs_fca_ub_alloc() */ static void @@ -3047,11 +3052,13 @@ emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp) ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; if (hba->state <= FC_LINK_DOWN) { + emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id); return; } if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) { + emlxs_abort_els_exchange(hba, port, ubp->ub_frame.rx_id); return; } @@ -3100,7 +3107,8 @@ emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp) } /* emlxs_ub_els_reject() */ extern int -emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) +emlxs_fca_ub_release(opaque_t fca_port_handle, uint32_t count, + uint64_t tokens[]) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -3112,14 +3120,15 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (count == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release: Nothing to do. count=%d", count); + "fca_ub_release: Nothing to do. count=%d", count); return (FC_SUCCESS); } if (!(port->flag & EMLXS_PORT_BOUND)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release failed: Port not bound. count=%d token[0]=%p", + "fca_ub_release failed: Port not bound. count=%d " + "token[0]=%p", count, tokens[0]); return (FC_UNBOUND); @@ -3129,7 +3138,7 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!port->ub_pool) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release failed: No pools! count=%d token[0]=%p", + "fca_ub_release failed: No pools! count=%d token[0]=%p", count, tokens[0]); mutex_exit(&EMLXS_UB_LOCK); @@ -3141,8 +3150,8 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!ubp) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release failed: count=%d tokens[%d]=0", count, - i); + "fca_ub_release failed: count=%d tokens[%d]=0", + count, i); mutex_exit(&EMLXS_UB_LOCK); return (FC_UB_BADTOKEN); @@ -3152,7 +3161,7 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release failed: Dead buffer found. ubp=%p", + "fca_ub_release failed: Dead buffer found. ubp=%p", ubp); mutex_exit(&EMLXS_UB_LOCK); @@ -3161,7 +3170,8 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (ub_priv->flags == EMLXS_UB_FREE) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_release: Buffer already free! ubp=%p token=%x", + "fca_ub_release: Buffer already free! ubp=%p " + "token=%x", ubp, ub_priv->token); continue; @@ -3191,7 +3201,8 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) } EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, - "ub_release: ubp=%p token=%x time=%d av=%d (%d,%d,%d,%d)", + "fca_ub_release: ubp=%p token=%x time=%d av=%d " + "(%d,%d,%d,%d)", ubp, ub_priv->token, time, ub_priv->available, pool->pool_nentries, pool->pool_available, pool->pool_free, pool->pool_free_resv); @@ -3208,11 +3219,11 @@ emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) return (FC_SUCCESS); -} /* emlxs_ub_release() */ +} /* emlxs_fca_ub_release() */ static int -emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) +emlxs_fca_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_unsol_buf_t *pool; @@ -3226,7 +3237,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (count == 0) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_free: Nothing to do. count=%d token[0]=%p", count, + "fca_ub_free: Nothing to do. count=%d token[0]=%p", count, tokens[0]); return (FC_SUCCESS); @@ -3234,7 +3245,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!(port->flag & EMLXS_PORT_BOUND)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_free: Port not bound. count=%d token[0]=%p", count, + "fca_ub_free: Port not bound. count=%d token[0]=%p", count, tokens[0]); return (FC_SUCCESS); @@ -3244,7 +3255,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!port->ub_pool) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_free failed: No pools! count=%d token[0]=%p", count, + "fca_ub_free failed: No pools! count=%d token[0]=%p", count, tokens[0]); mutex_exit(&EMLXS_UB_LOCK); @@ -3257,7 +3268,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!ubp) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_free failed: count=%d tokens[%d]=0", count, + "fca_ub_free failed: count=%d tokens[%d]=0", count, i); mutex_exit(&EMLXS_UB_LOCK); @@ -3269,7 +3280,8 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, - "ub_free failed: Dead buffer found. ubp=%p", ubp); + "fca_ub_free failed: Dead buffer found. ubp=%p", + ubp); mutex_exit(&EMLXS_UB_LOCK); return (FC_UB_BADTOKEN); @@ -3281,7 +3293,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) pool = ub_priv->pool; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, - "ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp, + "fca_ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp, ub_priv->token, pool->pool_nentries, pool->pool_available - 1, pool->pool_free, pool->pool_free_resv); @@ -3302,7 +3314,7 @@ emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) return (FC_SUCCESS); -} /* emlxs_ub_free() */ +} /* emlxs_fca_ub_free() */ /* EMLXS_UB_LOCK must be held when calling this routine */ @@ -3380,7 +3392,7 @@ emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool) /*ARGSUSED*/ extern int -emlxs_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) +emlxs_fca_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -3611,8 +3623,7 @@ begin: /* Free the ULPIOTAG and the bmp */ if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - hba->fc_table[sbp->iotag] = NULL; - emlxs_sli4_free_xri(hba, sbp, sbp->xp); + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); } else { (void) emlxs_unregister_pkt(cp, sbp->iotag, 1); } @@ -3801,7 +3812,7 @@ done: return (FC_SUCCESS); -} /* emlxs_pkt_abort() */ +} /* emlxs_fca_pkt_abort() */ static void @@ -3828,7 +3839,7 @@ emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip) flg = (sbp->pkt_flags & PACKET_IN_CHIPQ); pkt = PRIV2PKT(sbp); mutex_exit(&EMLXS_FCTAB_LOCK); - rc = emlxs_pkt_abort(port, pkt, 0); + rc = emlxs_fca_pkt_abort(port, pkt, 0); if (rc == FC_SUCCESS) { if (flg) { chipcnt++; @@ -3938,7 +3949,7 @@ emlxs_reset(emlxs_port_t *port, uint32_t cmd) } /* emlxs_reset() */ -static int32_t +extern int32_t emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; @@ -3997,7 +4008,7 @@ emlxs_fca_reset(opaque_t fca_port_handle, uint32_t cmd) extern int -emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) +emlxs_fca_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) { emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; emlxs_hba_t *hba = HBA; @@ -4232,7 +4243,7 @@ emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt; } - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); break; } @@ -4746,6 +4757,20 @@ emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) case EMLXS_HW_ERROR_TEST: { + /* + * This command is used for simulating HW ERROR + * on SLI4 only. + */ + if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { + ret = FC_INVALID_REQUEST; + break; + } + hba->sli.sli4.flag |= EMLXS_SLI4_HW_ERROR; + break; + } + + case EMLXS_MB_TIMEOUT_TEST: + { if (!(hba->flag & FC_ONLINE_MODE)) { return (FC_OFFLINE); } @@ -5115,7 +5140,7 @@ emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) ret = FC_FAILURE; break; } -#endif +#endif /* S11 */ default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, @@ -5127,7 +5152,7 @@ emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) return (ret); -} /* emlxs_port_manage() */ +} /* emlxs_fca_port_manage() */ /*ARGSUSED*/ @@ -5569,69 +5594,81 @@ emlxs_lock_init(emlxs_hba_t *hba) /* Initialize the power management */ (void) sprintf(buf, "%s%d_pm_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_PM_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_adap_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_TIMER_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_adap_lock cv", DRIVER_NAME, ddiinst); cv_init(&hba->timer_lock_cv, buf, CV_DRIVER, NULL); (void) sprintf(buf, "%s%d_port_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_PORT_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_mbox_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_MBOX_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_mbox_lock cv", DRIVER_NAME, ddiinst); cv_init(&EMLXS_MBOX_CV, buf, CV_DRIVER, NULL); (void) sprintf(buf, "%s%d_linkup_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_LINKUP_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_linkup_lock cv", DRIVER_NAME, ddiinst); cv_init(&EMLXS_LINKUP_CV, buf, CV_DRIVER, NULL); - (void) sprintf(buf, "%s%d_ring_tx_lock mutex", DRIVER_NAME, ddiinst); + (void) sprintf(buf, "%s%d_tx channel_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_TX_CHANNEL_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); for (i = 0; i < MAX_RINGS; i++) { (void) sprintf(buf, "%s%d_cmd_ring%d_lock mutex", DRIVER_NAME, ddiinst, i); mutex_init(&EMLXS_CMD_RING_LOCK(i), buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); } + + for (i = 0; i < EMLXS_MAX_WQS; i++) { + (void) sprintf(buf, "%s%d wq_cq_eq%d lock mutex", DRIVER_NAME, + ddiinst, i); + mutex_init(&EMLXS_QUE_LOCK(i), buf, MUTEX_DRIVER, + DDI_INTR_PRI(hba->intr_arg)); + } + + (void) sprintf(buf, "%s%d_msiid lock mutex", DRIVER_NAME, ddiinst); + mutex_init(&EMLXS_MSIID_LOCK, buf, MUTEX_DRIVER, + DDI_INTR_PRI(hba->intr_arg)); + (void) sprintf(buf, "%s%d_fctab_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_FCTAB_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_memget_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_MEMGET_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_memput_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_MEMPUT_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_ioctl_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_IOCTL_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); #ifdef DUMP_SUPPORT (void) sprintf(buf, "%s%d_dump mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_DUMP_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); #endif /* DUMP_SUPPORT */ (void) sprintf(buf, "%s%d_thread_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_SPAWN_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); /* Create per port locks */ for (i = 0; i < MAX_VPORTS; i++) { @@ -5643,7 +5680,7 @@ emlxs_lock_init(emlxs_hba_t *hba) (void) sprintf(buf, "%s%d_pkt_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_pkt_lock cv", DRIVER_NAME, ddiinst); @@ -5652,12 +5689,12 @@ emlxs_lock_init(emlxs_hba_t *hba) (void) sprintf(buf, "%s%d_ub_lock mutex", DRIVER_NAME, ddiinst); mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); } else { (void) sprintf(buf, "%s%d.%d_pkt_lock mutex", DRIVER_NAME, ddiinst, port->vpi); mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d.%d_pkt_lock cv", DRIVER_NAME, ddiinst, port->vpi); @@ -5666,7 +5703,7 @@ emlxs_lock_init(emlxs_hba_t *hba) (void) sprintf(buf, "%s%d.%d_ub_lock mutex", DRIVER_NAME, ddiinst, port->vpi); mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); } } @@ -5699,6 +5736,12 @@ emlxs_lock_destroy(emlxs_hba_t *hba) mutex_destroy(&EMLXS_CMD_RING_LOCK(i)); } + for (i = 0; i < EMLXS_MAX_WQS; i++) { + mutex_destroy(&EMLXS_QUE_LOCK(i)); + } + + mutex_destroy(&EMLXS_MSIID_LOCK); + mutex_destroy(&EMLXS_FCTAB_LOCK); mutex_destroy(&EMLXS_MEMGET_LOCK); mutex_destroy(&EMLXS_MEMPUT_LOCK); @@ -5775,7 +5818,9 @@ emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed) #ifdef SFCT_SUPPORT if (init_flag & ATTACH_FCT) { emlxs_fct_detach(hba); - emlxs_fct_modclose(); + if (hba->tgt_mode) { + emlxs_fct_modclose(); + } } #endif /* SFCT_SUPPORT */ @@ -5828,7 +5873,7 @@ emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed) #endif /* FMA_SUPPORT */ if (init_flag & ATTACH_LOG) { - (void) emlxs_msg_log_destroy(hba); + emlxs_msg_log_destroy(hba); } if (init_flag & ATTACH_FCA_TRAN) { @@ -6038,9 +6083,17 @@ emlxs_drv_banner(emlxs_hba_t *hba) emlxs_config_t *cfg = &CFG; uint8_t *wwpn; uint8_t *wwnn; + uint32_t fw_show = 0; + + /* Display firmware library one time for all driver instances */ + mutex_enter(&emlxs_device.lock); + if (! (emlxs_instance_flag & EMLXS_FW_SHOW)) { + emlxs_instance_flag |= EMLXS_FW_SHOW; + fw_show = 1; + } + mutex_exit(&emlxs_device.lock); - /* Display firmware library one time */ - if (emlxs_instance_count == 1) { + if (fw_show) { emlxs_fw_show(hba); } @@ -6333,16 +6386,6 @@ emlxs_hba_attach(dev_info_t *dip) /* We can begin to use EMLXS_MSGF from this point on */ - /* Create the event queue */ - if (emlxs_event_queue_create(hba) == 0) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, - "Unable to create event queue"); - - goto failed; - - } - init_flag |= ATTACH_EVENTS; - /* * Find the I/O bus type If it is not a SBUS card, * then it is a PCI card. Default is PCI_FC (0). @@ -6390,6 +6433,14 @@ emlxs_hba_attach(dev_info_t *dip) hba->model_info.device_id, hba->model_info.model); goto failed; } +#define FILTER_ORACLE_BRANDED +#ifdef FILTER_ORACLE_BRANDED + + /* Sun-branded adapters are not supported */ + if (hba->model_info.flags & EMLXS_SUN_BRANDED) { + hba->model_info.flags |= EMLXS_NOT_SUPPORTED; + } +#endif /* FILTER_ORACLE_BRANDED */ /* Check if adapter is not supported */ if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { @@ -6467,9 +6518,20 @@ emlxs_hba_attach(dev_info_t *dip) init_flag |= ATTACH_INTR_INIT; /* Initialize LOCKs */ + emlxs_msg_lock_reinit(hba); emlxs_lock_init(hba); init_flag |= ATTACH_LOCK; + /* Create the event queue */ + if (emlxs_event_queue_create(hba) == 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, + "Unable to create event queue"); + + goto failed; + + } + init_flag |= ATTACH_EVENTS; + /* Initialize the power management */ mutex_enter(&EMLXS_PM_LOCK); hba->pm_state = EMLXS_PM_IN_ATTACH; @@ -7339,7 +7401,7 @@ emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) if (buf_info->flags & FC_MBUF_PHYSONLY) { - if (buf_info->virt == 0) { + if (buf_info->virt == NULL) { goto done; } @@ -7432,7 +7494,7 @@ emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) "flags=%x", buf_info->size, buf_info->align, buf_info->flags); - buf_info->virt = 0; + buf_info->virt = NULL; buf_info->phys = 0; buf_info->data_handle = 0; buf_info->dma_handle = 0; @@ -7454,7 +7516,7 @@ emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) (void) ddi_dma_free_handle( (ddi_dma_handle_t *)&buf_info->dma_handle); - buf_info->virt = 0; + buf_info->virt = NULL; buf_info->phys = 0; buf_info->data_handle = 0; buf_info->dma_handle = 0; @@ -7480,7 +7542,7 @@ emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) (void) ddi_dma_free_handle( (ddi_dma_handle_t *)&buf_info->dma_handle); - buf_info->virt = 0; + buf_info->virt = NULL; buf_info->phys = 0; buf_info->dma_handle = 0; buf_info->data_handle = 0; @@ -7512,8 +7574,7 @@ emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) } else { /* allocate virtual memory */ buf_info->virt = - (uint32_t *)kmem_zalloc((size_t)buf_info->size, - KM_NOSLEEP); + kmem_zalloc((size_t)buf_info->size, KM_NOSLEEP); buf_info->phys = 0; buf_info->data_handle = 0; buf_info->dma_handle = 0; @@ -7585,42 +7646,11 @@ emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info) } /* emlxs_mem_free() */ -/* - * A channel has a association with a msi id. - * One msi id could be associated with multiple channels. - */ -static int -emlxs_next_chan(emlxs_hba_t *hba, int msi_id) -{ - emlxs_config_t *cfg = &CFG; - EQ_DESC_t *eqp; - int chan; - int num_wq; - - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - /* For SLI4 round robin all WQs associated with the msi_id */ - eqp = &hba->sli.sli4.eq[msi_id]; - num_wq = cfg[CFG_NUM_WQ].current; - - mutex_enter(&eqp->lastwq_lock); - chan = eqp->lastwq; - eqp->lastwq++; - if (eqp->lastwq >= ((msi_id + 1) * num_wq)) { - eqp->lastwq -= num_wq; - } - mutex_exit(&eqp->lastwq_lock); - - } else { - chan = hba->channel_fcp; - } - return (chan); -} - - static int emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset) { int channel; + int msi_id; /* IO to FCP2 device or a device reset always use fcp channel */ @@ -7628,7 +7658,10 @@ emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset) return (hba->channel_fcp); } - channel = emlxs_next_chan(hba, 0); + + msi_id = emlxs_select_msiid(hba); + channel = emlxs_msiid_to_chan(hba, msi_id); + /* If channel is closed, then try fcp channel */ @@ -7704,14 +7737,14 @@ emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp) emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0); } - (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); + emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); rc = FC_SUCCESS; } return (rc); } static int32_t -emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) +emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp, uint32_t *pkt_flags) { emlxs_hba_t *hba = HBA; fc_packet_t *pkt; @@ -7776,6 +7809,7 @@ emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) mutex_enter(&sbp->mtx); sbp->pkt_flags |= PACKET_FCP_TGT_RESET; sbp->pkt_flags |= PACKET_POLLED; + *pkt_flags = sbp->pkt_flags; mutex_exit(&sbp->mtx); #ifdef SAN_DIAG_SUPPORT @@ -7826,6 +7860,7 @@ emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) mutex_enter(&sbp->mtx); sbp->pkt_flags |= PACKET_FCP_LUN_RESET; sbp->pkt_flags |= PACKET_POLLED; + *pkt_flags = sbp->pkt_flags; mutex_exit(&sbp->mtx); #ifdef SAN_DIAG_SUPPORT @@ -7836,7 +7871,8 @@ emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) iocbq->flag |= IOCB_PRIORITY; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, - "LUN Reset: did=%x LUN=%02x02x", did, cmd[0], cmd[1]); + "LUN Reset: did=%x lun=%02x LUN=%02x02x", did, lun, + cmd[0], cmd[1]); /* Flush the IO's on the tx queues for this lun */ (void) emlxs_tx_lun_flush(port, ndlp, lun, sbp); @@ -7912,6 +7948,81 @@ emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) +/* + * We have to consider this setup works for INTX, MSI, and MSIX + * For INTX, intr_count is always 1 + * For MSI, intr_count is always 2 by default + * For MSIX, intr_count is configurable (1, 2, 4, 8) for now. + */ +extern int +emlxs_select_msiid(emlxs_hba_t *hba) +{ + int msiid = 0; + + /* We use round-robin */ + mutex_enter(&EMLXS_MSIID_LOCK); + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + msiid = hba->last_msiid; + hba->last_msiid ++; + if (hba->last_msiid >= hba->intr_count) { + hba->last_msiid = 0; + } + } else { + /* This should work for INTX and MSI also */ + /* For SLI3 the chan_count is always 4 */ + /* For SLI3 the msiid is limited to chan_count */ + msiid = hba->last_msiid; + hba->last_msiid ++; + if (hba->intr_count > hba->chan_count) { + if (hba->last_msiid >= hba->chan_count) { + hba->last_msiid = 0; + } + } else { + if (hba->last_msiid >= hba->intr_count) { + hba->last_msiid = 0; + } + } + } + mutex_exit(&EMLXS_MSIID_LOCK); + + return (msiid); +} /* emlxs_select_msiid */ + + +/* + * A channel has a association with a msi id. + * One msi id could be associated with multiple channels. + */ +extern int +emlxs_msiid_to_chan(emlxs_hba_t *hba, int msi_id) +{ + emlxs_config_t *cfg = &CFG; + EQ_DESC_t *eqp; + int chan; + int num_wq; + + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + /* For SLI4 round robin all WQs associated with the msi_id */ + eqp = &hba->sli.sli4.eq[msi_id]; + + mutex_enter(&eqp->lastwq_lock); + chan = eqp->lastwq; + eqp->lastwq++; + num_wq = cfg[CFG_NUM_WQ].current; + if (eqp->lastwq >= ((msi_id + 1) * num_wq)) { + eqp->lastwq -= num_wq; + } + mutex_exit(&eqp->lastwq_lock); + + return (chan); + } else { + /* This is for SLI3 mode */ + return (hba->msi2chan[msi_id]); + } + +} /* emlxs_msiid_to_chan */ + + #ifdef SFCT_SUPPORT static int32_t emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp) @@ -8183,7 +8294,7 @@ emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = (void *)ndlp; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = iocb->ULPCLASS; sbp->did = did; mutex_exit(&sbp->mtx); @@ -8216,6 +8327,7 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) char fcsp_msg[32]; int rc; int32_t rval; + emlxs_config_t *cfg = &CFG; fcsp_msg[0] = 0; pkt = PRIV2PKT(sbp); @@ -8236,32 +8348,47 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) /* Check node */ switch (cmd) { case ELS_CMD_FLOGI: - if (port->vpi > 0) { - if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { - if (!(port->flag & EMLXS_PORT_INIT_VPI_CMPL)) { - (void) emlxs_mb_init_vpi(port); - if (!(port->flag & - EMLXS_PORT_INIT_VPI_CMPL)) { - pkt->pkt_state = - FC_PKT_LOCAL_RJT; + case ELS_CMD_FDISC: + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + if (emlxs_vpi_logi_notify(port, sbp)) { + pkt->pkt_state = FC_PKT_LOCAL_RJT; +#if (EMLXS_MODREVX == EMLXS_MODREV2X) + emlxs_unswap_pkt(sbp); +#endif /* EMLXS_MODREV2X */ + return (FC_FAILURE); + } + } else { + /* + * If FLOGI is already complete, then we + * should not be receiving another FLOGI. + * Reset the link to recover. + */ + if (port->flag & EMLXS_PORT_FLOGI_CMPL) { + pkt->pkt_state = FC_PKT_LOCAL_RJT; #if (EMLXS_MODREVX == EMLXS_MODREV2X) - emlxs_unswap_pkt(sbp); + emlxs_unswap_pkt(sbp); #endif /* EMLXS_MODREV2X */ - return (FC_FAILURE); - } - } + (void) emlxs_reset(port, FC_FCA_LINK_RESET); + return (FC_FAILURE); + } + + if (port->vpi > 0) { + *((uint32_t *)pkt->pkt_cmd) = ELS_CMD_FDISC; } - cmd = ELS_CMD_FDISC; - *((uint32_t *)pkt->pkt_cmd) = cmd; } - ndlp = NULL; + + /* Command may have been changed */ + cmd = *((uint32_t *)pkt->pkt_cmd); + cmd &= ELS_CMD_MASK; if (hba->flag & FC_NPIV_DELAY_REQUIRED) { sbp->pkt_flags |= PACKET_DELAY_REQUIRED; } + ndlp = NULL; + /* We will process these cmds at the bottom of this routine */ break; @@ -8315,8 +8442,8 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { - (void) emlxs_mem_put(hba, MEM_MBOX, - (uint8_t *)mbox); + emlxs_mem_put(hba, MEM_MBOX, + (void *)mbox); } } @@ -8384,13 +8511,13 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) /* Check cmd */ switch (cmd) { case ELS_CMD_PRLI: - { /* * if our firmware version is 3.20 or later, * set the following bits for FC-TAPE support. */ - - if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) { + if (port->ini_mode && + (hba->vpd.feaLevelHigh >= 0x02) && + (cfg[CFG_ADISC_SUPPORT].current != 0)) { els_pkt->un.prli.ConfmComplAllowed = 1; els_pkt->un.prli.Retry = 1; els_pkt->un.prli.TaskRetryIdReq = 1; @@ -8398,22 +8525,20 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) els_pkt->un.prli.ConfmComplAllowed = 0; els_pkt->un.prli.Retry = 0; els_pkt->un.prli.TaskRetryIdReq = 0; - } - - break; } + break; + /* This is a patch for the ULP stack. */ /* - * ULP only reads our service paramters once during bind_port, + * ULP only reads our service parameters once during bind_port, * but the service parameters change due to topology. */ case ELS_CMD_FLOGI: case ELS_CMD_FDISC: case ELS_CMD_PLOGI: case ELS_CMD_PDISC: - { /* Copy latest service parameters to payload */ bcopy((void *) &port->sparam, (void *)&els_pkt->un.logi, sizeof (SERV_PARM)); @@ -8439,8 +8564,6 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) #endif /* DHCHAP_SUPPORT */ break; - } - } /* Initialize the sbp */ @@ -8448,7 +8571,7 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = (void *)ndlp; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->did = did; mutex_exit(&sbp->mtx); @@ -8463,17 +8586,19 @@ emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) /* Check node */ switch (cmd) { case ELS_CMD_FLOGI: + case ELS_CMD_FDISC: if (port->ini_mode) { /* Make sure fabric node is destroyed */ /* It should already have been destroyed at link down */ - /* Unregister the fabric did and attempt a deferred */ - /* iocb send */ if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { - if (emlxs_mb_unreg_did(port, FABRIC_DID, NULL, - NULL, iocbq) == 0) { - /* Deferring iocb tx until */ - /* completion of unreg */ - return (FC_SUCCESS); + ndlp = emlxs_node_find_did(port, FABRIC_DID); + if (ndlp) { + if (emlxs_mb_unreg_node(port, ndlp, + NULL, NULL, iocbq) == 0) { + /* Deferring iocb tx until */ + /* completion of unreg */ + return (FC_SUCCESS); + } } } } @@ -8779,8 +8904,9 @@ emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) if (cmd == ELS_CMD_ACC) { /* This is a patch for the ULP stack. */ /* ULP does not keep track of FCP2 support */ - - if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) { + if (port->ini_mode && + (hba->vpd.feaLevelHigh >= 0x02) && + (cfg[CFG_ADISC_SUPPORT].current != 0)) { els_pkt->un.prli.ConfmComplAllowed = 1; els_pkt->un.prli.Retry = 1; els_pkt->un.prli.TaskRetryIdReq = 1; @@ -8842,7 +8968,7 @@ emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = (void *) NULL; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = iocb->ULPCLASS; sbp->did = did; mutex_exit(&sbp->mtx); @@ -9058,7 +9184,7 @@ emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = (void *) ndlp; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = iocb->ULPCLASS; sbp->did = did; mutex_exit(&sbp->mtx); @@ -9126,7 +9252,7 @@ emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = (void *)ndlp; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = iocb->ULPCLASS; sbp->did = did; mutex_exit(&sbp->mtx); @@ -9229,7 +9355,7 @@ emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) sbp->ticks = hba->timer_tics + pkt->pkt_timeout + ((pkt->pkt_timeout > 0xff) ? 0 : 10); sbp->node = NULL; - sbp->lun = 0; + sbp->lun = EMLXS_LUN_NONE; sbp->class = iocb->ULPCLASS; mutex_exit(&sbp->mtx); @@ -9337,6 +9463,16 @@ emlxs_pkt_complete(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat, hba = HBA; + if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && + (sbp->iotag)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg, + "WARNING: Completing IO with iotag. sbp=%p iotag=%x " + "xri_flags=%x", + sbp, sbp->iotag, ((sbp->xrip)? sbp->xrip->flag:0)); + + emlxs_sli4_free_xri(hba, sbp, sbp->xrip, 1); + } + mutex_enter(&sbp->mtx); /* Check for error conditions */ @@ -9582,7 +9718,6 @@ emlxs_iodone(emlxs_buf_t *sbp) if (sbp->pkt_flags & PACKET_ULP_OWNED) { return; } - cp = (CHANNEL *)sbp->channel; #if (EMLXS_MODREVX == EMLXS_MODREV2X) emlxs_unswap_pkt(sbp); @@ -9596,7 +9731,12 @@ emlxs_iodone(emlxs_buf_t *sbp) #ifdef FMA_SUPPORT emlxs_check_dma(hba, sbp); #endif /* FMA_SUPPORT */ - cp->ulpCmplCmd++; + + if (sbp->channel) { + cp = (CHANNEL *)sbp->channel; + cp->ulpCmplCmd++; + } + (*pkt->pkt_comp) (pkt); } @@ -10597,6 +10737,7 @@ emlxs_pm_idle_timer(emlxs_hba_t *hba) #endif /* IDLE_TIMER */ +#if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) static void emlxs_read_vport_prop(emlxs_hba_t *hba) { @@ -10681,7 +10822,7 @@ emlxs_read_vport_prop(emlxs_hba_t *hba) errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -10725,7 +10866,7 @@ emlxs_read_vport_prop(emlxs_hba_t *hba) errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -10771,7 +10912,7 @@ emlxs_read_vport_prop(emlxs_hba_t *hba) errors++; } - *np++ = sum; + *np++ = (uint8_t)sum; } if (*s++ != ':') { @@ -10857,6 +10998,7 @@ out: return; } /* emlxs_read_vport_prop() */ +#endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */ extern char * @@ -10903,7 +11045,7 @@ emlxs_ub_flush(emlxs_port_t *port) ubp->ub_frame.type); } else { /* Drop the buffer */ - (void) emlxs_ub_release(port, 1, &ubp->ub_token); + (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token); } ub_priv = next; @@ -10929,7 +11071,7 @@ emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp) port->ulp_unsol_cb(port->ulp_handle, ubp, ubp->ub_frame.type); } else { - (void) emlxs_ub_release(port, 1, &ubp->ub_token); + (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token); } return; @@ -10950,7 +11092,7 @@ emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp) mutex_exit(&EMLXS_PORT_LOCK); } else { - (void) emlxs_ub_release(port, 1, &ubp->ub_token); + (void) emlxs_fca_ub_release(port, 1, &ubp->ub_token); } } diff --git a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_thread.c b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_thread.c index d35f8b9b2e..1db0fbc305 100644 --- a/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_thread.c +++ b/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_thread.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Emulex. All rights reserved. + * Copyright 2010 Emulex. All rights reserved. * Use is subject to license terms. */ @@ -161,7 +161,7 @@ emlxs_taskq_create(emlxs_hba_t *hba, emlxs_taskq_t *taskq) (void) sprintf(buf, "%s%d_thread_taskq_get mutex", DRIVER_NAME, hba->ddiinst); mutex_init(&taskq->get_lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); mutex_enter(&taskq->get_lock); @@ -170,7 +170,7 @@ emlxs_taskq_create(emlxs_hba_t *hba, emlxs_taskq_t *taskq) (void) sprintf(buf, "%s%d_thread_taskq_put mutex", DRIVER_NAME, hba->ddiinst); mutex_init(&taskq->put_lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); for (i = 0; i < EMLXS_MAX_TASKQ_THREADS; i++) { tthread = &taskq->thread_list[i]; @@ -179,7 +179,7 @@ emlxs_taskq_create(emlxs_hba_t *hba, emlxs_taskq_t *taskq) (void) sprintf(buf, "%s%d_thread%d mutex", DRIVER_NAME, hba->ddiinst, i); mutex_init(&tthread->lock, buf, MUTEX_DRIVER, - (void *)hba->intr_arg); + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_thread%d cv", DRIVER_NAME, hba->ddiinst, i); @@ -369,7 +369,8 @@ emlxs_thread_create(emlxs_hba_t *hba, emlxs_thread_t *ethread) (void) sprintf(buf, "%s%d_thread_%08x mutex", DRIVER_NAME, hba->ddiinst, (uint32_t)((uintptr_t)ethread & 0xFFFFFFFF)); - mutex_init(ðread->lock, buf, MUTEX_DRIVER, (void *)hba->intr_arg); + mutex_init(ðread->lock, buf, MUTEX_DRIVER, + DDI_INTR_PRI(hba->intr_arg)); (void) sprintf(buf, "%s%d_thread_%08x cv", DRIVER_NAME, hba->ddiinst, (uint32_t)((uintptr_t)ethread & 0xFFFFFFFF)); |
