summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/fibre-channel
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2012-01-25 22:01:17 -0800
committerGarrett D'Amore <garrett@damore.org>2012-01-25 22:01:17 -0800
commita9800beb32c1006bb21c8da39e0180ea440b7bad (patch)
tree2cf60f168e6ca0ee5db11e16fef4505c1fee4631 /usr/src/uts/common/io/fibre-channel
parent528b7d8ba791f2da280ff1ddd45c61eb47a2744e (diff)
downloadillumos-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')
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_clock.c57
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dfc.c161
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dhchap.c304
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_diag.c8
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_download.c722
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_dump.c186
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_els.c707
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_event.c45
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcf.c12960
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fcp.c341
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_fct.c67
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c186
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_ip.c6
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c2151
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mem.c194
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_msg.c80
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_node.c218
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_pkt.c8
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli3.c325
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_sli4.c1995
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_solaris.c766
-rw-r--r--usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_thread.c11
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(&ethread->lock, buf, MUTEX_DRIVER, (void *)hba->intr_arg);
+ mutex_init(&ethread->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));