diff options
author | Sukumar Swaminathan <Sukumar.Swaminathan@Sun.COM> | 2009-12-23 12:12:50 -0800 |
---|---|---|
committer | Sukumar Swaminathan <Sukumar.Swaminathan@Sun.COM> | 2009-12-23 12:12:50 -0800 |
commit | b3660a963b4e1d5319365d4d7c34beb66fb5abc7 (patch) | |
tree | 5db85949647f6909b745c70b079b95460c581819 /usr/src | |
parent | b885580b43755ee4ea1e280b85428893d2ba9291 (diff) | |
download | illumos-joyent-b3660a963b4e1d5319365d4d7c34beb66fb5abc7.tar.gz |
6911213 emlxs 2.50 driver queue list corruption for FCoE adapters
6902275 emlxs drivers sets DDI_FM_DMACHK_CAPABLE without correctly handling dma errors
Diffstat (limited to 'usr/src')
17 files changed, 844 insertions, 333 deletions
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 7d4afbfb34..82ff99ffb9 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 @@ -166,6 +166,8 @@ static int emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode); static int emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode); +static int emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc, + int32_t mode); uint32_t emlxs_loopback_tmo = 60; @@ -223,6 +225,7 @@ emlxs_table_t emlxs_dfc_table[] = { {EMLXS_RD_BE_FCF, "RD_BE_FCF"}, {EMLXS_SET_BE_DCBX, "SET_BE_DCBX"}, {EMLXS_GET_BE_DCBX, "GET_BE_DCBX"}, + {EMLXS_GET_QOS, "GET_QOS"}, }; /* emlxs_dfc_table */ @@ -784,6 +787,10 @@ emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode) rval = emlxs_dfc_get_be_dcbx(hba, dfc, mode); break; + case EMLXS_GET_QOS: + rval = emlxs_dfc_get_qos(hba, dfc, mode); + break; + default: EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "Unknown command received. (0x%x)", dfc->cmd); @@ -3033,52 +3040,27 @@ emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) els->elsCode = 0x04; /* FLOGI - This will be changed automatically */ /* by the drive (See emlxs_send_els()) */ - els->un.logi.cmn.fcphHigh = 0x09; - els->un.logi.cmn.fcphLow = 0x08; - els->un.logi.cmn.bbCreditMsb = 0xff; - els->un.logi.cmn.bbCreditlsb = 0xff; - els->un.logi.cmn.reqMultipleNPort = 1; - els->un.logi.cmn.bbRcvSizeMsb = 0x08; - els->un.logi.cmn.bbRcvSizeLsb = 0x00; - els->un.logi.cmn.w2.nPort.totalConcurrSeq = 0xff; - els->un.logi.cmn.w2.nPort.roByCategoryMsb = 0xff; - els->un.logi.cmn.w2.nPort.roByCategoryLsb = 0xff; - els->un.logi.cmn.e_d_tov = 0x7d0; + /* Copy latest service parameters to payload */ + bcopy((void *)&port->sparam, + (void *)&els->un.logi, sizeof (SERV_PARM)); bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8); wwn[0] = 0x28; wwn[1] = hba->vpi_max; bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8); + bcopy((caddr_t)wwn, (caddr_t)&vport->wwnn, 8); bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8); wwn[0] = 0x20; wwn[1] = hba->vpi_max; bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8); - - els->un.logi.cls1.openSeqPerXchgMsb = 0x00; - els->un.logi.cls1.openSeqPerXchgLsb = 0x01; - - els->un.logi.cls2.classValid = 1; - els->un.logi.cls2.rcvDataSizeMsb = 0x08; - els->un.logi.cls2.rcvDataSizeLsb = 0x00; - els->un.logi.cls2.concurrentSeqMsb = 0x00; - els->un.logi.cls2.concurrentSeqLsb = 0xff; - els->un.logi.cls2.EeCreditSeqMsb = 0x00; - els->un.logi.cls2.EeCreditSeqLsb = 0x0c; - els->un.logi.cls2.openSeqPerXchgMsb = 0x00; - els->un.logi.cls2.openSeqPerXchgLsb = 0x01; - - els->un.logi.cls3.classValid = 1; - els->un.logi.cls3.rcvDataSizeMsb = 0x08; - els->un.logi.cls3.rcvDataSizeLsb = 0x00; - els->un.logi.cls3.concurrentSeqMsb = 0x00; - els->un.logi.cls3.concurrentSeqLsb = 0xff; - els->un.logi.cls3.openSeqPerXchgMsb = 0x00; - els->un.logi.cls3.openSeqPerXchgLsb = 0x01; + bcopy((caddr_t)wwn, (caddr_t)&vport->wwpn, 8); bcopy((void *)&els->un.logi, (void *)&vport->sparam, sizeof (SERV_PARM)); + + /* Make this a polled IO */ pkt->pkt_tran_flags &= ~FC_TRAN_INTR; pkt->pkt_tran_flags |= FC_TRAN_NO_INTR; @@ -4650,10 +4632,34 @@ done: /* Free allocated mbuf memory */ if (rx_mp) { +#ifdef FMA_SUPPORT + if (!rval) { + if (emlxs_fm_check_dma_handle(hba, rx_mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_dfc_send_mbox: hdl=%p", + rx_mp->dma_handle); + rval = DFC_IO_ERROR; + } + } +#endif /* FMA_SUPPORT */ (void) emlxs_mem_buf_free(hba, rx_mp); } if (tx_mp) { +#ifdef FMA_SUPPORT + if (!rval) { + if (emlxs_fm_check_dma_handle(hba, tx_mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_dfc_send_mbox: hdl=%p", + tx_mp->dma_handle); + rval = DFC_IO_ERROR; + } + } +#endif /* FMA_SUPPORT */ (void) emlxs_mem_buf_free(hba, tx_mp); } @@ -10490,7 +10496,7 @@ emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) "%s: ddi_copyout failed. cmd=%x", emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand); - rval = DFC_COPYIN_ERROR; + rval = DFC_COPYOUT_ERROR; goto done; } } @@ -10700,3 +10706,32 @@ done: return (rval); } + + +static int +emlxs_dfc_get_qos(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode) +{ + emlxs_port_t *port = &PPORT; + uint32_t rval = 0; + + if (! (hba->model_info.flags & EMLXS_FCOE_SUPPORTED)) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, + "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd)); + + return (DFC_FCOE_NOTSUPPORTED); + } + + if (dfc->buf1_size) { + if (ddi_copyout((void *)&hba->qos_linkspeed, (void *)dfc->buf1, + dfc->buf1_size, mode) != 0) { + EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg, + "%s: ddi_copyout failed.", + emlxs_dfc_xlate(dfc->cmd)); + + rval = DFC_COPYOUT_ERROR; + return (rval); + } + } + + return (rval); +} 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 470e596e99..eaef06e270 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 @@ -397,9 +397,29 @@ emlxs_diag_biu_run(emlxs_hba_t *hba, uint32_t pattern) done: if (mp) { +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_diag_biu_run: hdl=%p", + mp->dma_handle); + rval = EMLXS_TEST_FAILED; + } +#endif /* FMA_SUPPORT */ (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); } if (mp1) { +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_diag_biu_run: hdl=%p", + mp1->dma_handle); + rval = EMLXS_TEST_FAILED; + } +#endif /* FMA_SUPPORT */ (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); } if (mbq) { 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 131b9247f1..c514029031 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 @@ -2794,6 +2794,19 @@ done: kmem_free(mbox, sizeof (MAILBOXQ)); } +#ifdef FMA_SUPPORT + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_read_wakeup_parms: hdl=%p", + hba->sli.sli4.dump_region.dma_handle); + rval = 1; + } + } +#endif /* FMA_SUPPORT */ + return (rval); } /* emlxs_read_wakeup_parms() */ @@ -2889,6 +2902,19 @@ done: kmem_free(mbox, sizeof (MAILBOXQ)); } +#ifdef FMA_SUPPORT + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_read_load_list: hdl=%p", + hba->sli.sli4.dump_region.dma_handle); + return (1); + } + } +#endif /* FMA_SUPPORT */ + return (0); } /* emlxs_read_load_list() */ @@ -4408,6 +4434,19 @@ Exit_Function: kmem_free(mbox, sizeof (MAILBOXQ)); } +#ifdef FMA_SUPPORT + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_get_max_sram: hdl=%p", + hba->sli.sli4.dump_region.dma_handle); + rval = 1; + } + } +#endif /* FMA_SUPPORT */ + return (rval); } /* emlxs_get_max_sram() */ 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 68cbccb1fe..63a4e97e1c 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 @@ -3777,6 +3777,17 @@ emlxs_dump_saturn_log( SID_NON_VOLATILE_LOG, LEGEND_NON_VOLATILE_LOG, LEGEND_NULL, fSwap); +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_dump_saturn_log: hdl=%p", + mp->dma_handle); + status = 1; + } +#endif /* FMA_SUPPORT */ + (void) emlxs_mem_buf_free(hba, mp); kmem_free(mbq, sizeof (MAILBOXQ)); return (status); 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 b2fb0586f0..6dca92af23 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 @@ -158,9 +158,21 @@ emlxs_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) #if (EMLXS_MODREVX == EMLXS_MODREV2X) emlxs_unswap_pkt(sbp); #endif /* EMLXS_MODREV2X */ + +#ifdef FMA_SUPPORT + emlxs_check_dma(hba, sbp); +#endif /* FMA_SUPPORT */ + cp->ulpCmplCmd++; (*pkt->pkt_comp) (pkt); +#ifdef FMA_SUPPORT + if (hba->flag & FC_DMA_CHECK_ERROR) { + emlxs_thread_spawn(hba, emlxs_restart_thread, + NULL, NULL); + } +#endif /* FMA_SUPPORT */ + return; } 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 7aa0cf2899..dd04d0b08a 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 @@ -83,7 +83,8 @@ static stmf_data_buf_t *emlxs_fct_dbuf_alloc(fct_local_port_t *fct_port, uint32_t size, uint32_t *pminsize, uint32_t flags); static void emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf); -static void emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type); +static int emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf, + uint_t sync_type); static emlxs_buf_t *emlxs_fct_pkt_init(emlxs_port_t *port, fct_cmd_t *fct_cmd, fc_packet_t *pkt); @@ -96,7 +97,6 @@ static uint32_t emlxs_fct_pkt_abort_txq(emlxs_port_t *port, emlxs_buf_t *cmd_sbp); static fct_status_t emlxs_fct_send_qfull_reply(emlxs_port_t *port, emlxs_node_t *ndlp, uint16_t xid, uint32_t class, emlxs_fcp_cmd_t *fcp_cmd); -static void emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type); #ifdef FCT_IO_TRACE uint8_t *emlxs_iotrace = 0; /* global for mdb */ @@ -2535,7 +2535,7 @@ emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf, int channel; int channelno; - fct_status_t rval; + fct_status_t rval = 0; rval = emlxs_fct_cmd_accept(port, fct_cmd, EMLXS_FCT_SEND_FCP_DATA); if (rval) { @@ -2588,7 +2588,12 @@ emlxs_fct_send_fcp_data(fct_cmd_t *fct_cmd, stmf_data_buf_t *dbuf, } if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { - emlxs_fct_dbuf_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV); + if (emlxs_fct_dbuf_dma_sync(hba, dbuf, DDI_DMA_SYNC_FORDEV)) { + emlxs_fct_cmd_post(port, fct_cmd, EMLXS_FCT_CMD_POSTED); + /* mutex_exit(&cmd_sbp->fct_mtx); */ + + return (FCT_BUSY); + } } cmd_sbp->fct_flags |= EMLXS_FCT_IO_INP; @@ -2902,6 +2907,7 @@ emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) fct_cmd->cmd_comp_status = FCT_SUCCESS; if (status) { +emlxs_dma_error: /* * The error indicates this IO should be terminated * immediately. @@ -2935,8 +2941,10 @@ emlxs_fct_handle_fcp_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) case CMD_FCP_TRECEIVE64_CX: if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) { - emlxs_fct_dbuf_dma_sync(dbuf, - DDI_DMA_SYNC_FORCPU); + if (emlxs_fct_dbuf_dma_sync(hba, dbuf, + DDI_DMA_SYNC_FORCPU)) { + goto emlxs_dma_error; + } } if ((cmd_sbp->fct_flags & EMLXS_FCT_SEND_STATUS) && @@ -3818,6 +3826,20 @@ emlxs_fct_pkt_comp(fc_packet_t *pkt) fct_cmd, fct_cmd->cmd_comp_status); #endif /* FCT_API_TRACE */ +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_fct_pkt_comp: hdl=%p", + pkt->pkt_resp_dma); + MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE, + FCT_IOF_FCA_DONE); + + break; + } +#endif /* FMA_SUPPORT */ + MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE); @@ -3848,6 +3870,19 @@ emlxs_fct_pkt_comp(fc_packet_t *pkt) fct_cmd, fct_cmd->cmd_comp_status); #endif /* FCT_API_TRACE */ +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_fct_pkt_comp: hdl=%p", + pkt->pkt_resp_dma); + MODSYM(fct_send_cmd_done) (fct_cmd, FCT_FAILURE, + FCT_IOF_FCA_DONE); + + break; + } +#endif /* FMA_SUPPORT */ MODSYM(fct_send_cmd_done) (fct_cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE); @@ -4988,17 +5023,33 @@ emlxs_fct_dbuf_free(fct_dbuf_store_t *fds, stmf_data_buf_t *dbuf) } /* emlxs_fct_dbuf_free() */ -static void -emlxs_fct_dbuf_dma_sync(stmf_data_buf_t *dbuf, uint_t sync_type) +static int +emlxs_fct_dbuf_dma_sync(emlxs_hba_t *hba, stmf_data_buf_t *dbuf, + uint_t sync_type) { emlxs_fct_dmem_bctl_t *bctl = (emlxs_fct_dmem_bctl_t *)dbuf->db_port_private; emlxs_fct_dmem_bucket_t *p = bctl->bctl_bucket; + emlxs_port_t *port = &PPORT; + int retval = 0; (void) ddi_dma_sync(p->dmem_dma_handle, (unsigned long)(bctl->bctl_dev_addr - p->dmem_dev_addr), dbuf->db_data_size, sync_type); +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, p->dmem_dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_fct_dbuf_dma_sync: hdl=%p", + p->dmem_dma_handle); + retval = 1; + } +#endif /* FMA_SUPPORT */ + + return (retval); + } /* emlxs_fct_dbuf_dma_sync() */ 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 822f379ddb..204515c70a 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 @@ -487,6 +487,9 @@ emlxs_mbext_add_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) 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); @@ -540,13 +543,14 @@ emlxs_mbext_add_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index) #endif if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) { - uint16_t i; - uint8_t bitmap[512]; - 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; @@ -3562,6 +3566,7 @@ 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->flag & FC_NPIV_ENABLED)) { @@ -3600,6 +3605,12 @@ emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp) 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); @@ -3858,9 +3869,6 @@ emlxs_mb_get(emlxs_hba_t *hba) void emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo) { -#ifdef FMA_SUPPORT - emlxs_port_t *port = &PPORT; -#endif /* FMA_SUPPORT */ MATCHMAP *mp; HBASTATS.MboxIssued++; 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 ade7643d18..7b672d6bd4 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 @@ -929,6 +929,32 @@ reset: EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, DDI_DMA_SYNC_FORKERNEL); +#ifdef FMA_SUPPORT + if (mp->dma_handle) { + if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli3_online: hdl=%p", + mp->dma_handle); + rval = EIO; + goto failed; + } + } + + if (mp1->dma_handle) { + if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli3_online: hdl=%p", + mp1->dma_handle); + rval = EIO; + goto failed; + } + } +#endif /* FMA_SUPPORT */ + outptr = mp->virt; inptr = mp1->virt; @@ -4991,6 +5017,19 @@ emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) goto dropped; } +#ifdef FMA_SUPPORT + if (mp->dma_handle) { + if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_handle_rcv_seq: hdl=%p", + mp->dma_handle); + goto dropped; + } + } +#endif /* FMA_SUPPORT */ + if (!size) { (void) strcpy(error_str, "Buffer empty:"); goto dropped; @@ -5574,6 +5613,22 @@ emlxs_reset_ring(emlxs_hba_t *hba, uint32_t ringno) 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() */ 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 9aa820a2ae..0bc4936b3c 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 @@ -406,6 +406,22 @@ emlxs_data_dump(hba, "RD_REV", (uint32_t *)mb, 18, 0); EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0, mb->un.varDmp4.rsp_cnt, DDI_DMA_SYNC_FORKERNEL); +#ifdef FMA_SUPPORT + if (hba->sli.sli4.dump_region.dma_handle) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.dump_region.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_online: hdl=%p", + hba->sli.sli4.dump_region. + dma_handle); + rval = EIO; + goto failed1; + } + } +#endif /* FMA_SUPPORT */ + } } @@ -1403,6 +1419,16 @@ emlxs_data_dump(hba, "EndianIN", (uint32_t *)iptr, 6, 0); MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); emlxs_data_dump(hba, "EndianOUT", (uint32_t *)iptr, 6, 0); +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, hba->sli.sli4.bootstrapmb.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_init_bootstrap_mb: hdl=%p", + hba->sli.sli4.bootstrapmb.dma_handle); + return (1); + } +#endif hba->flag |= FC_BOOTSTRAPMB_INIT; return (0); @@ -1806,6 +1832,7 @@ emlxs_sli4_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) uint32_t flag; uint32_t wqdb; uint32_t next_wqe; + off_t offset; channelno = cp->channelno; @@ -1996,7 +2023,12 @@ sendit: #ifdef DEBUG_WQE emlxs_data_dump(hba, "WQE", (uint32_t *)wqe, 18, 0); #endif - EMLXS_MPDATA_SYNC(wq->addr.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + wq->addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + EMLXS_MPDATA_SYNC(wq->addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORDEV); /* Ring the WQ Doorbell */ @@ -2073,6 +2105,7 @@ emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) MATCHMAP *mp; uint32_t *iptr; uint32_t mqdb; + off_t offset; mbq = (MAILBOXQ *)mb; mb4 = (MAILBOX4 *)mb; @@ -2117,7 +2150,12 @@ emlxs_sli4_issue_mq(emlxs_hba_t *hba, MAILBOX4 *mqe, MAILBOX *mb, uint32_t tmo) BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mqe, MAILBOX_CMD_SLI4_BSIZE); - EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + hba->sli.sli4.mq.addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + 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); @@ -2146,8 +2184,9 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) emlxs_port_t *port = &PPORT; MAILBOXQ *mbq; MAILBOX4 *mb4; - MATCHMAP *mp; + MATCHMAP *mp = NULL; uint32_t *iptr; + int nonembed = 0; mbq = (MAILBOXQ *)mb; mb4 = (MAILBOX4 *)mb; @@ -2175,6 +2214,7 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) * mp will point to the actual mailbox command which * should be copied into the non-embedded area. */ + nonembed = 1; mb4->un.varSLIConfig.be.sge_cnt = 1; mb4->un.varSLIConfig.be.payload_length = mp->size; iptr = (uint32_t *)&mb4->un.varSLIConfig.be.un_hdr.hdr_req; @@ -2239,6 +2279,29 @@ emlxs_sli4_issue_bootstrap(emlxs_hba_t *hba, MAILBOX *mb, uint32_t tmo) emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0); } +#ifdef FMA_SUPPORT + if (nonembed && mp) { + if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_issue_bootstrap: mp_hdl=%p", + mp->dma_handle); + return (MBXERR_DMA_ERROR); + } + } + + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.bootstrapmb.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_issue_bootstrap: hdl=%p", + hba->sli.sli4.bootstrapmb.dma_handle); + return (MBXERR_DMA_ERROR); + } +#endif + return (MBX_SUCCESS); } /* emlxs_sli4_issue_bootstrap() */ @@ -2640,6 +2703,7 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) NODELIST *node; uint16_t iotag; uint32_t did; + off_t offset; pkt = PRIV2PKT(sbp); did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); @@ -2707,7 +2771,12 @@ emlxs_sli4_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) emlxs_data_dump(hba, "FCP CMD", (uint32_t *)pkt->pkt_cmd, 10, 0); #endif - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + xp->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); /* if device is FCP-2 device, set the following bit */ @@ -2785,6 +2854,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) ddi_dma_cookie_t *cp_cmd; ddi_dma_cookie_t *cp_resp; emlxs_node_t *node; + off_t offset; pkt = PRIV2PKT(sbp); did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); @@ -2925,7 +2995,7 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) sge->addrHigh = PADDR_HI(cp_resp->dmac_laddress); sge->addrLow = PADDR_LO(cp_resp->dmac_laddress); sge->length = pkt->pkt_rsplen; - sge->offset = pkt->pkt_cmdlen; + sge->offset = 0; sge->last = 1; /* Now sge is fully staged */ @@ -2987,7 +3057,12 @@ emlxs_sli4_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) wqe->Timer = ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); } - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + xp->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); if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_CHAINED_SEQ) { @@ -3027,6 +3102,7 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) RPIobj_t *rp; XRIobj_t *xp; uint32_t did; + off_t offset; pkt = PRIV2PKT(sbp); did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); @@ -3169,7 +3245,12 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; iocb->ULPPU = 1; /* Wd4 is relative offset */ - EMLXS_MPDATA_SYNC(xp->SGList.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + xp->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); wqe->ContextTag = rp->RPI; @@ -3202,12 +3283,12 @@ emlxs_sli4_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) static int emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) { - emlxs_port_t *port = &PPORT; 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; @@ -3216,7 +3297,12 @@ emlxs_sli4_poll_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) shost_index = host_index; - EMLXS_MPDATA_SYNC(eq->addr.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + eq->addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORKERNEL); mutex_enter(&EMLXS_PORT_LOCK); @@ -3341,6 +3427,7 @@ emlxs_sli4_process_async_event(emlxs_hba_t *hba, CQE_ASYNC_t *cqe) hba->linkspeed = LA_10GHZ_LINK; } hba->topology = TOPOLOGY_PT_PT; + hba->qos_linkspeed = cqe->qos_link_speed; /* * This link is not really up till we have @@ -3414,6 +3501,7 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) uint32_t size; uint32_t *iptr; int rc; + off_t offset; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "CQ ENTRY: process mbox event"); @@ -3463,8 +3551,13 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) return; } + offset = (off_t)((uint64_t)((unsigned long) + hba->sli.sli4.mq.addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + /* Now that we are the owner, DMA Sync entire MQ if needed */ - EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, 0, + EMLXS_MPDATA_SYNC(hba->sli.sli4.mq.addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORDEV); BE_SWAP32_BCOPY((uint8_t *)hba->mbox_mqe, (uint8_t *)mb, @@ -3487,6 +3580,17 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) mbox_bp = (MATCHMAP *)mbq->bp; EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size, DDI_DMA_SYNC_FORKERNEL); +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, mbox_bp->dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_process_mbox_event: hdl=%p", + mbox_bp->dma_handle); + + mb->mbxStatus = MBXERR_DMA_ERROR; +} +#endif } /* Now sync the memory buffer if one was used */ @@ -3498,6 +3602,17 @@ emlxs_sli4_process_mbox_event(emlxs_hba_t *hba, CQE_MBOX_t *cqe) iptr = (uint32_t *)((uint8_t *)mbox_nonembed->virt); BE_SWAP32_BCOPY((uint8_t *)iptr, (uint8_t *)iptr, size); +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, + mbox_nonembed->dma_handle) != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_process_mbox_event: hdl=%p", + mbox_nonembed->dma_handle); + + mb->mbxStatus = MBXERR_DMA_ERROR; + } +#endif emlxs_data_dump(hba, "EXT AREA", (uint32_t *)iptr, 24, 0); } @@ -4004,8 +4119,8 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, emlxs_port_t *vport; RQ_DESC_t *hdr_rq; RQ_DESC_t *data_rq; - MATCHMAP *hdr_mp; - MATCHMAP *data_mp; + MBUF_INFO *hdr_mp; + MBUF_INFO *data_mp; MATCHMAP *seq_mp; uint32_t *data; fc_frame_hdr_t fchdr; @@ -4028,6 +4143,7 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, uint32_t cmd; uint32_t posted = 0; uint32_t abort = 1; + off_t offset; hdr_rqi = hba->sli.sli4.rq_map[cqe->RQid]; hdr_rq = &hba->sli.sli4.rq[hdr_rqi]; @@ -4086,9 +4202,12 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, mutex_exit(&hba->sli.sli4.rq[hdr_rqi].lock); /* Get the next header rqb */ - hdr_mp = hdr_rq->rqb[host_index]; + hdr_mp = &hdr_rq->rqb[host_index]; + + offset = (off_t)((uint64_t)((unsigned long)hdr_mp->virt) - + (uint64_t)((unsigned long)hba->sli.sli4.slim2.virt)); - EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, 0, + EMLXS_MPDATA_SYNC(hdr_mp->dma_handle, offset, sizeof (fc_frame_hdr_t), DDI_DMA_SYNC_FORKERNEL); LE_SWAP32_BCOPY(hdr_mp->virt, (uint8_t *)&fchdr, @@ -4278,9 +4397,14 @@ emlxs_sli4_process_unsol_rcv(emlxs_hba_t *hba, CQ_DESC_t *cq, /* Save the frame data to our seq buffer */ if (cqe->data_size && seq_mp) { /* Get the next data rqb */ - data_mp = data_rq->rqb[host_index]; + data_mp = &data_rq->rqb[host_index]; - EMLXS_MPDATA_SYNC(data_mp->dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + data_mp->virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + EMLXS_MPDATA_SYNC(data_mp->dma_handle, offset, cqe->data_size, DDI_DMA_SYNC_FORKERNEL); data = (uint32_t *)data_mp->virt; @@ -4551,6 +4675,19 @@ done: (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); } +#ifdef FMA_SUPPORT + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.slim2.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_process_unsol_rcv: hdl=%p", + hba->sli.sli4.slim2.dma_handle); + + emlxs_thread_spawn(hba, emlxs_restart_thread, + NULL, NULL); + } +#endif return; } /* emlxs_sli4_process_unsol_rcv() */ @@ -4597,13 +4734,19 @@ emlxs_sli4_process_cq(emlxs_hba_t *hba, CQ_DESC_t *cq) CQE_u cq_entry; uint32_t cqdb; int num_entries = 0; + off_t offset; /* EMLXS_PORT_LOCK must be held when entering this routine */ cqe = (CQE_u *)cq->addr.virt; cqe += cq->host_index; - EMLXS_MPDATA_SYNC(cq->addr.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + cq->addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + EMLXS_MPDATA_SYNC(cq->addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORKERNEL); for (;;) { @@ -4709,13 +4852,19 @@ emlxs_sli4_process_eq(emlxs_hba_t *hba, EQ_DESC_t *eq) uint32_t i; uint32_t value; int num_entries = 0; + off_t offset; /* EMLXS_PORT_LOCK must be held when entering this routine */ ptr = eq->addr.virt; ptr += eq->host_index; - EMLXS_MPDATA_SYNC(eq->addr.dma_handle, 0, + offset = (off_t)((uint64_t)((unsigned long) + eq->addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + + EMLXS_MPDATA_SYNC(eq->addr.dma_handle, offset, 4096, DDI_DMA_SYNC_FORKERNEL); for (;;) { @@ -4940,7 +5089,6 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) { emlxs_port_t *port = &PPORT; MBUF_INFO *buf_info; - XRIobj_t *xp; uint32_t i; if (hba->sli.sli4.FCFIp) { @@ -4961,8 +5109,6 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) buf_info = &hba->sli.sli4.HeaderTmplate; if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); bzero(buf_info, sizeof (MBUF_INFO)); } @@ -4977,74 +5123,43 @@ emlxs_sli4_resource_free(emlxs_hba_t *hba) hba->sli.sli4.XRIinuse_b, &hba->sli.sli4.XRIinuse_f); } - xp = hba->sli.sli4.XRIp; - for (i = 0; i < hba->sli.sli4.XRICount; i++) { - buf_info = &xp->SGList; - if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); - bzero(buf_info, sizeof (MBUF_INFO)); - } - xp++; - } kmem_free(hba->sli.sli4.XRIp, (sizeof (XRIobj_t) * hba->sli.sli4.XRICount)); hba->sli.sli4.XRIp = NULL; - hba->sli.sli4.XRIfree_tail = NULL; - hba->sli.sli4.XRIfree_list = NULL; + + hba->sli.sli4.XRIfree_f = + (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.XRIfree_b = + (XRIobj_t *)&hba->sli.sli4.XRIfree_f; hba->sli.sli4.xrif_count = 0; } for (i = 0; i < EMLXS_MAX_EQS; i++) { - buf_info = &hba->sli.sli4.eq[i].addr; - if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); - mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock); - } + mutex_destroy(&hba->sli.sli4.eq[i].lastwq_lock); bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t)); } for (i = 0; i < EMLXS_MAX_CQS; i++) { - buf_info = &hba->sli.sli4.cq[i].addr; - if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); - } bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t)); } for (i = 0; i < EMLXS_MAX_WQS; i++) { - buf_info = &hba->sli.sli4.wq[i].addr; - if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); - } bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t)); } for (i = 0; i < EMLXS_MAX_RQS; i++) { - /* Free the RQ */ - buf_info = &hba->sli.sli4.rq[i].addr; - if (buf_info->virt) { - buf_info->flags = FC_MBUF_DMA; - emlxs_mem_free(hba, buf_info); - - /* Free the RQB pool */ - emlxs_mem_pool_free(hba, &hba->sli.sli4.rq[i].rqb_pool); - mutex_destroy(&hba->sli.sli4.rq[i].lock); - - /* Free the associated RXQ */ - mutex_destroy(&hba->sli.sli4.rxq[i].lock); - bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t)); - } + mutex_destroy(&hba->sli.sli4.rq[i].lock); + mutex_destroy(&hba->sli.sli4.rxq[i].lock); + bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t)); bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t)); } /* Free the MQ */ - buf_info = &hba->sli.sli4.mq.addr; - if (buf_info->virt == NULL) { + bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); + + buf_info = &hba->sli.sli4.slim2; + if (buf_info->virt) { buf_info->flags = FC_MBUF_DMA; emlxs_mem_free(hba, buf_info); + bzero(buf_info, sizeof (MBUF_INFO)); } - bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); /* Cleanup queue ordinal mapping */ for (i = 0; i < EMLXS_MAX_EQ_IDS; i++) { @@ -5080,10 +5195,17 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) RPIobj_t *rp; XRIobj_t *xp; char buf[64]; - emlxs_memseg_t *seg; - MATCHMAP *mp; - MATCHMAP **rqb; RQE_t *rqe; + MBUF_INFO *rqb; + uint64_t phys; + uint64_t tmp_phys; + char *virt; + char *tmp_virt; + void *data_handle; + void *dma_handle; + int32_t size; + 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); @@ -5130,106 +5252,72 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) } } - if ((!hba->sli.sli4.XRIp) && (hba->sli.sli4.XRICount)) { - hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc( - (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP); - - xp = hba->sli.sli4.XRIp; - index = hba->sli.sli4.XRIBase; - for (i = 0; i < hba->sli.sli4.XRICount; i++) { - xp->sge_count = - (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64)); - xp->XRI = index; - xp->iotag = i; - if ((xp->XRI == 0) || (xp->iotag == 0)) { - index++; /* Skip XRI 0 or IOTag 0 */ - xp++; - continue; - } - /* Add xp to end of single linked free list */ - if (hba->sli.sli4.XRIfree_tail) { - hba->sli.sli4.XRIfree_tail->_f = xp; - hba->sli.sli4.XRIfree_tail = xp; - } else { - hba->sli.sli4.XRIfree_tail = xp; - } - if (hba->sli.sli4.XRIfree_list == NULL) { - hba->sli.sli4.XRIfree_list = xp; - } - xp->_f = NULL; - hba->sli.sli4.xrif_count++; - - /* Allocate SGL for this xp */ - buf_info = &xp->SGList; - buf_info->size = hba->sli.sli4.mem_sgl_size; - buf_info->flags = - FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; - buf_info->align = hba->sli.sli4.mem_sgl_size; + /* EQs - 1 per Interrupt vector */ + num_eq = hba->intr_count; + /* CQs - number of WQs + 1 for RQs + 1 for mbox/async events */ + num_wq = cfg[CFG_NUM_WQ].current * num_eq; - (void) emlxs_mem_alloc(hba, buf_info); + /* Calculate total dmable memory we need */ + /* EQ */ + count += num_eq * 4096; + /* CQ */ + count += (num_wq + EMLXS_CQ_OFFSET_WQ) * 4096; + /* WQ */ + count += num_wq * (4096 * EMLXS_NUM_WQ_PAGES); + /* MQ */ + count += EMLXS_MAX_MQS * 4096; + /* RQ */ + count += EMLXS_MAX_RQS * 4096; + /* RQB/E */ + count += RQB_COUNT * (RQB_DATA_SIZE + RQB_HEADER_SIZE); + /* SGL */ + count += hba->sli.sli4.XRICount * hba->sli.sli4.mem_sgl_size; + /* RPI Head Template */ + count += hba->sli.sli4.RPICount * sizeof (RPIHdrTmplate_t); + + /* Allocate slim2 for SLI4 */ + buf_info = &hba->sli.sli4.slim2; + buf_info->size = count; + buf_info->flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; + buf_info->align = ddi_ptob(hba->dip, 1L); + + (void) emlxs_mem_alloc(hba, buf_info); - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Unable to allocate XRI SGL area: %d", - hba->sli.sli4.mem_sgl_size); - goto failed; - } - bzero(buf_info->virt, hba->sli.sli4.mem_sgl_size); - xp++; - index++; - } - /* Initialize double linked list */ - hba->sli.sli4.XRIinuse_f = - (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; - hba->sli.sli4.XRIinuse_b = - (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; - hba->sli.sli4.xria_count = 0; + if (buf_info->virt == NULL) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_init_failed_msg, + "Unable to allocate internal memory for SLI4: %d", + count); + goto failed; } + bzero(buf_info->virt, buf_info->size); + EMLXS_MPDATA_SYNC(buf_info->dma_handle, 0, + buf_info->size, DDI_DMA_SYNC_FORDEV); - buf_info = &hba->sli.sli4.HeaderTmplate; - if ((buf_info->virt == NULL) && (hba->sli.sli4.RPICount)) { - bzero(buf_info, sizeof (MBUF_INFO)); - buf_info->size = (sizeof (RPIHdrTmplate_t) * - hba->sli.sli4.RPICount); - buf_info->flags = - FC_MBUF_DMA | FC_MBUF_DMA32; - buf_info->align = ddi_ptob(hba->dip, 1L); - - (void) emlxs_mem_alloc(hba, buf_info); - - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to allocate Header Tmplate area: %d", - (sizeof (RPIHdrTmplate_t) * - hba->sli.sli4.RPICount)); - goto failed; - } - bzero(buf_info->virt, - (sizeof (RPIHdrTmplate_t) * hba->sli.sli4.RPICount)); - } + /* Assign memory to SGL, Head Template, EQ, CQ, WQ, RQ and MQ */ + data_handle = buf_info->data_handle; + dma_handle = buf_info->dma_handle; + phys = buf_info->phys; + virt = (char *)buf_info->virt; /* Allocate space for queues */ - /* EQs - 1 per Interrupt vector */ - num_eq = hba->intr_count; + size = 4096; for (i = 0; i < num_eq; i++) { buf_info = &hba->sli.sli4.eq[i].addr; if (buf_info->virt == NULL) { bzero(&hba->sli.sli4.eq[i], sizeof (EQ_DESC_t)); - buf_info->size = 4096; + buf_info->size = size; buf_info->flags = 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; - (void) emlxs_mem_alloc(hba, buf_info); + phys += size; + virt += size; - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Unable to allocate EQ %d area", i); - goto failed; - } - bzero(buf_info->virt, 4096); hba->sli.sli4.eq[i].max_index = EQ_DEPTH; } @@ -5238,53 +5326,71 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) mutex_init(&hba->sli.sli4.eq[i].lastwq_lock, buf, MUTEX_DRIVER, NULL); } - /* CQs - number of WQs + 1 for RQs + 1 for mbox/async events */ - num_wq = cfg[CFG_NUM_WQ].current * num_eq; + + size = 4096; for (i = 0; i < (num_wq + EMLXS_CQ_OFFSET_WQ); i++) { buf_info = &hba->sli.sli4.cq[i].addr; if (buf_info->virt == NULL) { bzero(&hba->sli.sli4.cq[i], sizeof (CQ_DESC_t)); - buf_info->size = 4096; + buf_info->size = size; buf_info->flags = 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; - (void) emlxs_mem_alloc(hba, buf_info); + phys += size; + virt += size; - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Unable to allocate CQ %d area", i); - goto failed; - } - bzero(buf_info->virt, 4096); hba->sli.sli4.cq[i].max_index = CQ_DEPTH; } } + /* WQs - NUM_WQ config parameter * number of EQs */ + size = 4096 * EMLXS_NUM_WQ_PAGES; for (i = 0; i < num_wq; i++) { buf_info = &hba->sli.sli4.wq[i].addr; if (buf_info->virt == NULL) { bzero(&hba->sli.sli4.wq[i], sizeof (WQ_DESC_t)); - buf_info->size = (4096 * EMLXS_NUM_WQ_PAGES); + buf_info->size = size; buf_info->flags = 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; - (void) emlxs_mem_alloc(hba, buf_info); + phys += size; + virt += size; - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Unable to allocate WQ %d area", i); - goto failed; - } - bzero(buf_info->virt, (4096 * EMLXS_NUM_WQ_PAGES)); hba->sli.sli4.wq[i].max_index = WQ_DEPTH; hba->sli.sli4.wq[i].release_depth = WQE_RELEASE_DEPTH; } } + /* MQ */ + size = 4096; + buf_info = &hba->sli.sli4.mq.addr; + if (!buf_info->virt) { + bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); + buf_info->size = size; + buf_info->flags = + 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; + + phys += size; + virt += size; + + hba->sli.sli4.mq.max_index = MQ_DEPTH; + } + /* RXQs */ for (i = 0; i < EMLXS_MAX_RXQS; i++) { bzero(&hba->sli.sli4.rxq[i], sizeof (RXQ_DESC_t)); @@ -5294,6 +5400,7 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) } /* RQs */ + size = 4096; for (i = 0; i < EMLXS_MAX_RQS; i++) { buf_info = &hba->sli.sli4.rq[i].addr; if (buf_info->virt) { @@ -5301,107 +5408,157 @@ emlxs_sli4_resource_alloc(emlxs_hba_t *hba) } bzero(&hba->sli.sli4.rq[i], sizeof (RQ_DESC_t)); - buf_info->size = 4096; + buf_info->size = size; buf_info->flags = 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; - (void) emlxs_mem_alloc(hba, buf_info); + phys += size; + virt += size; - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, - &emlxs_init_failed_msg, - "Unable to allocate RQ %d area", i); - goto failed; - } - bzero(buf_info->virt, 4096); hba->sli.sli4.rq[i].max_index = RQ_DEPTH; - /* RQBs */ - seg = &hba->sli.sli4.rq[i].rqb_pool; - bzero(seg, sizeof (MEMSEG)); - seg->fc_numblks = RQB_COUNT; - seg->fc_memflag = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; - seg->fc_memalign = 8; - seg->fc_memtag = (i<<16); - - if ((i & 0x1)) { - /* Odd == Data pool */ - seg->fc_memsize = RQB_DATA_SIZE; - (void) strcpy(seg->fc_label, "RQB Data Pool"); - - } else { - /* Even == Header pool */ - seg->fc_memsize = RQB_HEADER_SIZE; - (void) strcpy(seg->fc_label, "RQB Header Pool"); - } - - /* Allocate the pool */ - if (emlxs_mem_pool_alloc(hba, seg) == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to allocate RQ %d pool", i); + (void) sprintf(buf, "%s_rq%d_lock mutex", DRIVER_NAME, i); + mutex_init(&hba->sli.sli4.rq[i].lock, buf, MUTEX_DRIVER, NULL); + } - goto failed; - } + /* Setup RQE */ + for (i = 0; i < EMLXS_MAX_RQS; i++) { + size = (i & 0x1) ? RQB_DATA_SIZE : RQB_HEADER_SIZE; + tmp_phys = phys; + tmp_virt = virt; /* Initialize the RQEs */ rqe = (RQE_t *)hba->sli.sli4.rq[i].addr.virt; - rqb = hba->sli.sli4.rq[i].rqb; - for (j = 0; j < (RQ_DEPTH/RQB_COUNT); j++) { - mp = (MATCHMAP*)seg->fc_memget_ptr; + phys = tmp_phys; + virt = tmp_virt; for (k = 0; k < RQB_COUNT; k++) { - if (j == 0) { - mp->tag = (seg->fc_memtag | k); - } - - word = PADDR_HI(mp->phys); + word = PADDR_HI(phys); rqe->AddrHi = BE_SWAP32(word); - word = PADDR_LO(mp->phys); + word = PADDR_LO(phys); rqe->AddrLo = BE_SWAP32(word); - *rqb = mp; - + rqb = &hba->sli.sli4.rq[i]. + rqb[k + (j * RQB_COUNT)]; + rqb->size = size; + rqb->flags = FC_MBUF_DMA | + FC_MBUF_SNGLSG | FC_MBUF_DMA32; + rqb->align = ddi_ptob(hba->dip, 1L); + rqb->phys = phys; + rqb->virt = virt; + rqb->data_handle = data_handle; + rqb->dma_handle = dma_handle; + + phys += size; + virt += size; #ifdef RQ_DEBUG EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, "RQ_ALLOC: rq[%d] rqb[%d,%d]=%p tag=%08x", i, j, k, mp, mp->tag); #endif - mp = (MATCHMAP *)mp->fc_mptr; rqe++; - rqb++; } } + offset = (off_t)((uint64_t)((unsigned long) + hba->sli.sli4.rq[i].addr.virt) - + (uint64_t)((unsigned long) + hba->sli.sli4.slim2.virt)); + /* Sync the RQ buffer list */ - EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, 0, + EMLXS_MPDATA_SYNC(hba->sli.sli4.rq[i].addr.dma_handle, offset, hba->sli.sli4.rq[i].addr.size, DDI_DMA_SYNC_FORDEV); + } - (void) sprintf(buf, "%s_rq%d_lock mutex", DRIVER_NAME, i); - mutex_init(&hba->sli.sli4.rq[i].lock, buf, MUTEX_DRIVER, NULL); + if ((!hba->sli.sli4.XRIp) && (hba->sli.sli4.XRICount)) { + /* Initialize double linked lists */ + hba->sli.sli4.XRIinuse_f = + (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; + hba->sli.sli4.XRIinuse_b = + (XRIobj_t *)&hba->sli.sli4.XRIinuse_f; + hba->sli.sli4.xria_count = 0; + + hba->sli.sli4.XRIfree_f = + (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.XRIfree_b = + (XRIobj_t *)&hba->sli.sli4.XRIfree_f; + hba->sli.sli4.xria_count = 0; + + hba->sli.sli4.XRIp = (XRIobj_t *)kmem_zalloc( + (sizeof (XRIobj_t) * hba->sli.sli4.XRICount), KM_SLEEP); + + xp = 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 = + (hba->sli.sli4.mem_sgl_size / sizeof (ULP_SGE64)); + xp->XRI = index; + xp->iotag = i; + if ((xp->XRI == 0) || (xp->iotag == 0)) { + index++; /* Skip XRI 0 or IOTag 0 */ + xp++; + 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; + hba->sli.sli4.xrif_count++; + + /* Allocate SGL for this xp */ + buf_info = &xp->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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; + + phys += size; + virt += size; + + xp++; + index++; + } } - /* MQ */ - buf_info = &hba->sli.sli4.mq.addr; - if (!buf_info->virt) { - bzero(&hba->sli.sli4.mq, sizeof (MQ_DESC_t)); - buf_info->size = 4096; - buf_info->flags = - FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; + size = sizeof (RPIHdrTmplate_t) * hba->sli.sli4.RPICount; + buf_info = &hba->sli.sli4.HeaderTmplate; + if ((buf_info->virt == NULL) && (hba->sli.sli4.RPICount)) { + bzero(buf_info, sizeof (MBUF_INFO)); + buf_info->size = size; + 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->data_handle = data_handle; + buf_info->dma_handle = dma_handle; + } - (void) emlxs_mem_alloc(hba, buf_info); - - if (buf_info->virt == NULL) { - EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, - "Unable to allocate MQ area"); +#ifdef FMA_SUPPORT + if (hba->sli.sli4.slim2.dma_handle) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.slim2.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "emlxs_sli4_resource_alloc: hdl=%p", + hba->sli.sli4.slim2.dma_handle); goto failed; } - bzero(buf_info->virt, 4096); - hba->sli.sli4.mq.max_index = MQ_DEPTH; } +#endif return (0); @@ -5565,9 +5722,9 @@ emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp) mutex_enter(&EMLXS_FCTAB_LOCK); - xp = hba->sli.sli4.XRIfree_list; + xp = hba->sli.sli4.XRIfree_f; - if (xp == NULL) { + if (xp == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, @@ -5600,8 +5757,10 @@ emlxs_sli4_reserve_xri(emlxs_hba_t *hba, RPIobj_t *rp) } /* Take it off free list */ - hba->sli.sli4.XRIfree_list = xp->_f; + (xp->_b)->_f = xp->_f; + (xp->_f)->_b = xp->_b; xp->_f = NULL; + xp->_b = NULL; hba->sli.sli4.xrif_count--; /* Add it to end of inuse list */ @@ -5661,8 +5820,10 @@ emlxs_sli4_unreserve_xri(emlxs_hba_t *hba, uint16_t xri) hba->sli.sli4.xria_count--; /* Add it to end of free list */ - hba->sli.sli4.XRIfree_tail->_f = xp; - hba->sli.sli4.XRIfree_tail = xp; + 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; hba->sli.sli4.xrif_count++; EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, @@ -5747,9 +5908,9 @@ emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rp) mutex_enter(&EMLXS_FCTAB_LOCK); - xp = hba->sli.sli4.XRIfree_list; + xp = hba->sli.sli4.XRIfree_f; - if (xp == NULL) { + if (xp == (XRIobj_t *)&hba->sli.sli4.XRIfree_f) { mutex_exit(&EMLXS_FCTAB_LOCK); EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg, @@ -5789,8 +5950,10 @@ emlxs_sli4_alloc_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, RPIobj_t *rp) } /* Take it off free list */ - hba->sli.sli4.XRIfree_list = xp->_f; + (xp->_b)->_f = xp->_f; + (xp->_f)->_b = xp->_b; xp->_f = NULL; + xp->_b = NULL; hba->sli.sli4.xrif_count--; /* Add it to end of inuse list */ @@ -6049,8 +6212,10 @@ emlxs_sli4_free_xri(emlxs_hba_t *hba, emlxs_buf_t *sbp, XRIobj_t *xp) hba->sli.sli4.xria_count--; /* Add it to end of free list */ - hba->sli.sli4.XRIfree_tail->_f = xp; - hba->sli.sli4.XRIfree_tail = xp; + 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; hba->sli.sli4.xrif_count++; } 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 c1b063ceef..66c4c645c6 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 @@ -2581,6 +2581,7 @@ emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp) clock_t time; uint32_t att_bit; CHANNEL *cp; + int in_panic = 0; mutex_enter(&EMLXS_PORT_LOCK); hba->io_poll_count++; @@ -2590,6 +2591,7 @@ emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp) cp = (CHANNEL *)sbp->channel; if (ddi_in_panic()) { + in_panic = 1; /* * In panic situations there will be one thread with * no interrrupts (hard or soft) and no timers @@ -2752,12 +2754,25 @@ done: hba->io_poll_count--; mutex_exit(&EMLXS_PORT_LOCK); +#ifdef FMA_SUPPORT + if (!in_panic) { + emlxs_check_dma(hba, sbp); + } +#endif + /* Make ULP completion callback if required */ if (pkt->pkt_comp) { cp->ulpCmplCmd++; (*pkt->pkt_comp) (pkt); } +#ifdef FMA_SUPPORT + if (hba->flag & FC_DMA_CHECK_ERROR) { + emlxs_thread_spawn(hba, emlxs_restart_thread, + NULL, NULL); + } +#endif + return; } /* emlxs_poll() */ @@ -9482,6 +9497,13 @@ emlxs_iodone_server(void *arg1, void *arg2, void *arg3) mutex_exit(&EMLXS_PORT_LOCK); +#ifdef FMA_SUPPORT + if (hba->flag & FC_DMA_CHECK_ERROR) { + emlxs_thread_spawn(hba, emlxs_restart_thread, + NULL, NULL); + } +#endif /* FMA_SUPPORT */ + return; } /* End emlxs_iodone_server */ @@ -9490,6 +9512,11 @@ emlxs_iodone_server(void *arg1, void *arg2, void *arg3) static void emlxs_iodone(emlxs_buf_t *sbp) { +#ifdef FMA_SUPPORT + emlxs_port_t *port = sbp->port; + emlxs_hba_t *hba = port->hba; +#endif /* FMA_SUPPORT */ + fc_packet_t *pkt; CHANNEL *cp; @@ -9510,6 +9537,9 @@ emlxs_iodone(emlxs_buf_t *sbp) mutex_exit(&sbp->mtx); if (pkt->pkt_comp) { +#ifdef FMA_SUPPORT + emlxs_check_dma(hba, sbp); +#endif /* FMA_SUPPORT */ cp->ulpCmplCmd++; (*pkt->pkt_comp) (pkt); } @@ -11017,9 +11047,6 @@ emlxs_fm_init(emlxs_hba_t *hba) if (DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { emlxs_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; emlxs_data_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; - } else { - emlxs_dev_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; - emlxs_data_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; } if (DDI_FM_DMA_ERR_CAP(hba->fm_caps)) { @@ -11155,6 +11182,8 @@ emlxs_fm_service_impact(emlxs_hba_t *hba, int impact) ddi_fm_service_impact(hba->dip, impact); + return; + } /* emlxs_fm_service_impact() */ @@ -11175,6 +11204,103 @@ emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, return (err->fme_status); } /* emlxs_fm_error_cb() */ + +extern void +emlxs_check_dma(emlxs_hba_t *hba, emlxs_buf_t *sbp) +{ + emlxs_port_t *port = sbp->port; + fc_packet_t *pkt = PRIV2PKT(sbp); + + if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { + if (emlxs_fm_check_dma_handle(hba, + hba->sli.sli4.slim2.dma_handle) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "slim2: hdl=%p", + hba->sli.sli4.slim2.dma_handle); + + mutex_enter(&EMLXS_PORT_LOCK); + hba->flag |= FC_DMA_CHECK_ERROR; + mutex_exit(&EMLXS_PORT_LOCK); + } + } else { + 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, + "slim2: hdl=%p", + hba->sli.sli3.slim2.dma_handle); + + mutex_enter(&EMLXS_PORT_LOCK); + hba->flag |= FC_DMA_CHECK_ERROR; + mutex_exit(&EMLXS_PORT_LOCK); + } + } + + if (hba->flag & FC_DMA_CHECK_ERROR) { + pkt->pkt_state = FC_PKT_TRAN_ERROR; + pkt->pkt_reason = FC_REASON_DMA_ERROR; + pkt->pkt_expln = FC_EXPLN_NONE; + pkt->pkt_action = FC_ACTION_RETRYABLE; + return; + } + + if (pkt->pkt_cmdlen) { + if (emlxs_fm_check_dma_handle(hba, pkt->pkt_cmd_dma) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "pkt_cmd_dma: hdl=%p", + pkt->pkt_cmd_dma); + + pkt->pkt_state = FC_PKT_TRAN_ERROR; + pkt->pkt_reason = FC_REASON_DMA_ERROR; + pkt->pkt_expln = FC_EXPLN_NONE; + pkt->pkt_action = FC_ACTION_RETRYABLE; + + return; + } + } + + if (pkt->pkt_rsplen) { + if (emlxs_fm_check_dma_handle(hba, pkt->pkt_resp_dma) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "pkt_resp_dma: hdl=%p", + pkt->pkt_resp_dma); + + pkt->pkt_state = FC_PKT_TRAN_ERROR; + pkt->pkt_reason = FC_REASON_DMA_ERROR; + pkt->pkt_expln = FC_EXPLN_NONE; + pkt->pkt_action = FC_ACTION_RETRYABLE; + + return; + } + } + + if (pkt->pkt_datalen) { + if (emlxs_fm_check_dma_handle(hba, pkt->pkt_data_dma) + != DDI_FM_OK) { + EMLXS_MSGF(EMLXS_CONTEXT, + &emlxs_invalid_dma_handle_msg, + "pkt_data_dma: hdl=%p", + pkt->pkt_data_dma); + + pkt->pkt_state = FC_PKT_TRAN_ERROR; + pkt->pkt_reason = FC_REASON_DMA_ERROR; + pkt->pkt_expln = FC_EXPLN_NONE; + pkt->pkt_action = FC_ACTION_RETRYABLE; + + return; + } + } + + return; + +} #endif /* FMA_SUPPORT */ diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_dfc.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_dfc.h index 8a19ca417a..7559fd7d02 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_dfc.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_dfc.h @@ -176,6 +176,7 @@ typedef struct sd_bucket_info #define EMLXS_RD_BE_FCF 82 #define EMLXS_SET_BE_DCBX 83 #define EMLXS_GET_BE_DCBX 84 +#define EMLXS_GET_QOS 85 /* SAN DIAG SUPPORT */ #define EMLXS_SD_SET_BUCKET 100 diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h index 8be3cf912a..12f551013f 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_extern.h @@ -224,6 +224,8 @@ extern void emlxs_fm_service_impact(emlxs_hba_t *hba, extern int emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data); +extern void emlxs_check_dma(emlxs_hba_t *hba, + emlxs_buf_t *sbp); #endif /* FMA_SUPPORT */ /* Module emlxs_pkt.c External Routine Declarations */ diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h index bc4e50300f..51a0b89938 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_fc.h @@ -1456,8 +1456,7 @@ typedef struct RQ_DESC uint16_t cqid; MBUF_INFO addr; - MEMSEG rqb_pool; - MATCHMAP *rqb[RQ_DEPTH]; + MBUF_INFO rqb[RQ_DEPTH]; kmutex_t lock; @@ -1627,15 +1626,17 @@ typedef struct emlxs_sli4 tlv_fcoe_t cfgFCOE; tlv_fcfconnectlist_t cfgFCF; + MBUF_INFO slim2; MBUF_INFO dump_region; #define EMLXS_DUMP_REGION_SIZE 1024 RPIobj_t *RPIp; MBUF_INFO HeaderTmplate; XRIobj_t *XRIp; - /* Single linked list for available XRIs */ - XRIobj_t *XRIfree_list; - XRIobj_t *XRIfree_tail; + + /* Double linked list for available XRIs */ + XRIobj_t *XRIfree_f; + XRIobj_t *XRIfree_b; uint32_t xrif_count; uint32_t mem_sgl_size; @@ -1727,6 +1728,7 @@ typedef struct emlxs_hba uint32_t link_event_tag; uint8_t topology; uint8_t linkspeed; + uint16_t qos_linkspeed; uint32_t linkup_wait_flag; kcondvar_t linkup_lock_cv; kmutex_t linkup_lock; @@ -1804,6 +1806,8 @@ typedef struct emlxs_hba /* over temperature event */ #define FC_MBOX_TIMEOUT 0x20000000 /* FC_ERROR reason: */ /* mailbox timeout event */ +#define FC_DMA_CHECK_ERROR 0x40000000 /* Shared memory (slim,..) */ + /* DMA handle went bad */ #define FC_HARDWARE_ERROR 0x80000000 /* FC_ERROR state triggered */ #define FC_RESET_MASK 0x00030C1F /* Bits to protect during */ diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h index 094163307c..3ede834f4a 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_mbox.h @@ -1868,8 +1868,7 @@ typedef struct uint32_t rsvd1; uint32_t rsvd2:8; uint32_t sid:24; - uint32_t rsvd3; - uint32_t rsvd4; + uint32_t portname[2]; /* N_PORT name */ uint32_t rsvd5; uint16_t vfi; uint16_t vpi; @@ -1878,8 +1877,7 @@ typedef struct uint32_t rsvd1; uint32_t sid:24; uint32_t rsvd2:8; - uint32_t rsvd3; - uint32_t rsvd4; + uint32_t portname[2]; /* N_PORT name */ uint32_t rsvd5; uint16_t vpi; uint16_t vfi; @@ -1953,8 +1951,7 @@ typedef struct uint16_t vpi; uint16_t fcfi; - uint32_t rsvd3; - uint32_t rsvd4; + uint32_t portname[2]; /* N_PORT name */ ULP_BDE64 bde; @@ -1974,8 +1971,7 @@ typedef struct uint16_t fcfi; uint16_t vpi; - uint32_t rsvd3; - uint32_t rsvd4; + uint32_t portname[2]; /* N_PORT name */ ULP_BDE64 bde; diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_os.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_os.h index e7a2226b8e..d846254d95 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_os.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_os.h @@ -302,27 +302,11 @@ extern void ddi_fm_acc_err_clear(); #define DELAYMS(ms) drv_usecwait((ms*1000)) #define DELAYUS(us) drv_usecwait(us) -#ifdef FMA_SUPPORT -#define EMLXS_MPDATA_SYNC(h, a, b, c) \ - if (h) { \ - (void) ddi_dma_sync((ddi_dma_handle_t)(h), \ - (off_t)(a), (size_t)(b), (uint_t)c); \ - if (emlxs_fm_check_dma_handle(hba, h) != DDI_FM_OK) { \ - EMLXS_MSGF(EMLXS_CONTEXT, \ - &emlxs_invalid_dma_handle_msg, \ - "ddi_dma_sync hdl=%p off=%x " \ - "size=%d dir=%x ", \ - h, a, b, c); \ - } \ - } -#else /* !FMA_SUPPORT */ #define EMLXS_MPDATA_SYNC(h, a, b, c) \ if (h) { \ (void) ddi_dma_sync((ddi_dma_handle_t)(h), \ (off_t)(a), (size_t)(b), (uint_t)c); \ } -#endif /* FMA_SUPPORT */ - #define PKT2PRIV(pkt) ((emlxs_buf_t *)(pkt)->pkt_fca_private) #define PRIV2PKT(sbp) sbp->pkt diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_queue.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_queue.h index 536824b584..c410fe935f 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_queue.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_queue.h @@ -267,8 +267,9 @@ typedef struct CQE_ASYNC uint8_t link_status; uint8_t phys_port; - uint32_t Rsvd1: 24; /* Word 1 */ - uint32_t port_fault: 8; + uint16_t qos_link_speed; /* Word 1 */ + uint8_t Rsvd1; + uint8_t port_fault; uint32_t event_tag; /* Word 2 */ @@ -285,8 +286,9 @@ typedef struct CQE_ASYNC uint8_t port_duplex; uint8_t port_speed; /* Word 0 */ - uint32_t port_fault: 8; - uint32_t Rsvd1: 24; /* Word 1 */ + uint8_t port_fault; /* Word 1 */ + uint8_t Rsvd1; + uint16_t qos_link_speed; uint32_t event_tag; /* Word 2 */ diff --git a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h index 6fd91ec7dc..a8579afff5 100644 --- a/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h +++ b/usr/src/uts/common/sys/fibre-channel/fca/emlxs/emlxs_version.h @@ -31,10 +31,10 @@ extern "C" { #endif -#define EMLXS_VERSION "2.50m" +#define EMLXS_VERSION "2.50n" #define EMLXS_DATE_MINUTE "00" /* 00-59 */ #define EMLXS_DATE_HOUR "16" /* 00-23 */ -#define EMLXS_DATE_DAY "08" /* 00-31 */ +#define EMLXS_DATE_DAY "14" /* 00-31 */ #define EMLXS_DATE_MONTH "12" /* 01-12 */ #define EMLXS_DATE_YEAR "2009" /* YYYY */ |