summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2016-04-12 18:50:37 +0000
committermav <mav@FreeBSD.org>2016-04-12 18:50:37 +0000
commit59b487552b970f0667b23ad1197bc0a224a5048c (patch)
treeabc1f17169c05712b6b0eef4d05b320bd9d32222 /sys/dev/isp/isp.c
parent39eee0515d3e628f1f86fbc6c0067659978b9f7e (diff)
downloadFreeBSD-src-59b487552b970f0667b23ad1197bc0a224a5048c.zip
FreeBSD-src-59b487552b970f0667b23ad1197bc0a224a5048c.tar.gz
Make all CT Pass-Through (name server requests) asynchronous.
Previously we had to do it synchronously because we could not drop the lock due to potential scratch memory use conflicts. Previous commits fixed that collision, so here it goes -- slower and less reliable external requests are executed asynchronously without spinning in tight loop and with more safe timeout handling.
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c135
1 files changed, 78 insertions, 57 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 88ea7de..2664d13 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -3078,20 +3078,31 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
fcp->isp_fabric_params = mbs.param[7];
fcp->isp_sns_hdl = NPH_SNS_ID;
r = isp_register_fc4_type_24xx(isp, chan);
- if (r == 0)
- isp_register_fc4_features_24xx(isp, chan);
- isp_register_port_name_24xx(isp, chan);
+ if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+ goto abort;
+ if (r != 0)
+ goto not_on_fabric;
+ r = isp_register_fc4_features_24xx(isp, chan);
+ if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+ goto abort;
+ if (r != 0)
+ goto not_on_fabric;
+ r = isp_register_port_name_24xx(isp, chan);
+ if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+ goto abort;
+ if (r != 0)
+ goto not_on_fabric;
isp_register_node_name_24xx(isp, chan);
+ if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+ goto abort;
} else {
fcp->isp_sns_hdl = SNS_ID;
r = isp_register_fc4_type(isp, chan);
- if (r == 0 && fcp->role == ISP_ROLE_TARGET)
+ if (r != 0)
+ goto not_on_fabric;
+ if (fcp->role == ISP_ROLE_TARGET)
isp_send_change_request(isp, chan);
}
- if (r) {
- isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__);
- return (-1);
- }
}
not_on_fabric:
@@ -3505,65 +3516,66 @@ isp_gid_ft_sns(ispsoftc_t *isp, int chan)
static int
isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
{
- mbreg_t mbs;
fcparam *fcp = FCPARAM(isp, chan);
- union {
- isp_ct_pt_t plocal;
- uint8_t q[QENTRY_LEN];
- } un;
- isp_ct_pt_t *pt;
- uint8_t *scp = fcp->isp_scratch;
+ isp_ct_pt_t pt;
+ void *reqp;
+ uint8_t resp[QENTRY_LEN];
/*
* Build a Passthrough IOCB in memory.
*/
- pt = &un.plocal;
- ISP_MEMZERO(un.q, QENTRY_LEN);
- pt->ctp_header.rqs_entry_count = 1;
- pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
- pt->ctp_handle = 0xffffffff;
- pt->ctp_nphdl = fcp->isp_sns_hdl;
- pt->ctp_cmd_cnt = 1;
- pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
- pt->ctp_time = 10;
- pt->ctp_rsp_cnt = 1;
- pt->ctp_rsp_bcnt = rsp_bcnt;
- pt->ctp_cmd_bcnt = cmd_bcnt;
- pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
- pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
- pt->ctp_dataseg[0].ds_count = cmd_bcnt;
- pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
- pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
- pt->ctp_dataseg[1].ds_count = rsp_bcnt;
- isp_put_ct_pt(isp, pt, (isp_ct_pt_t *)&scp[CTXOFF]);
- if (isp->isp_dblev & ISP_LOGDEBUG1)
- isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, &scp[CTXOFF]);
+ ISP_MEMZERO(&pt, sizeof(pt));
+ pt.ctp_header.rqs_entry_count = 1;
+ pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+ pt.ctp_nphdl = fcp->isp_sns_hdl;
+ pt.ctp_cmd_cnt = 1;
+ pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
+ pt.ctp_time = 10;
+ pt.ctp_rsp_cnt = 1;
+ pt.ctp_rsp_bcnt = rsp_bcnt;
+ pt.ctp_cmd_bcnt = cmd_bcnt;
+ pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+ pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+ pt.ctp_dataseg[0].ds_count = cmd_bcnt;
+ pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
+ pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
+ pt.ctp_dataseg[1].ds_count = rsp_bcnt;
- /*
- * Execute the Passthrough IOCB.
- */
- ISP_MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
- MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
- MBCMD_DEFAULT_TIMEOUT + pt->ctp_time * 1000000);
- mbs.param[1] = QENTRY_LEN;
- mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
- mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
- mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
- mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
- MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN, chan);
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ /* Prepare space for response in memory */
+ memset(resp, 0xff, sizeof(resp));
+ pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+ if (pt.ctp_handle == 0) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: CTP of Chan %d out of handles", __func__, chan);
return (-1);
}
- MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
+
+ /* Send request and wait for response. */
+ reqp = isp_getrqentry(isp);
+ if (reqp == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: CTP of Chan %d out of rqent", __func__, chan);
+ isp_destroy_handle(isp, pt.ctp_handle);
+ return (-1);
+ }
+ isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp);
if (isp->isp_dblev & ISP_LOGDEBUG1)
- isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, &scp[ZTXOFF]);
- pt = &un.plocal;
- isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
- if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) {
+ isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp);
+ ISP_SYNC_REQUEST(isp);
+ if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: CTP of Chan %d timed out", __func__, chan);
+ isp_destroy_handle(isp, pt.ctp_handle);
+ return (-1);
+ }
+ if (isp->isp_dblev & ISP_LOGDEBUG1)
+ isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp);
+
+ isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
+ if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
isp_prt(isp, ISP_LOGWARN,
"Chan %d GID_FT CT Passthrough returned 0x%x",
- chan, pt->ctp_status);
+ chan, pt.ctp_status);
return (-1);
}
@@ -3931,7 +3943,13 @@ isp_send_change_request(ispsoftc_t *isp, int chan)
mbs.param[1] = 0x03;
mbs.param[9] = chan;
isp_mboxcmd(isp, &mbs);
- return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : -1);
+ if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
+ return (0);
+ } else {
+ isp_prt(isp, ISP_LOGWARN, "Chan %d Send Change Request: 0x%x",
+ chan, mbs.param[0]);
+ return (-1);
+ }
}
static int
@@ -3970,6 +3988,8 @@ isp_register_fc4_type(ispsoftc_t *isp, int chan)
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
return (0);
} else {
+ isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x",
+ chan, mbs.param[0]);
return (-1);
}
}
@@ -6140,6 +6160,7 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt
}
}
return (1);
+ case RQSTYPE_CT_PASSTHRU:
case RQSTYPE_VP_MODIFY:
case RQSTYPE_VP_CTRL:
case RQSTYPE_LOGIN:
OpenPOWER on IntegriCloud