svn commit: r292739 - head/sys/dev/isp
Alexander Motin
mav at FreeBSD.org
Sat Dec 26 04:26:34 UTC 2015
Author: mav
Date: Sat Dec 26 04:26:32 2015
New Revision: 292739
URL: https://svnweb.freebsd.org/changeset/base/292739
Log:
Make virtual ports control asynchronous.
Before this change virtual ports control IOCBs were executed synchronously
via Execute IOCB mailbox command. It required exclusive use of scratch
space of driver and mailbox registers of the hardware. Because of that
shared resources use this code could not really sleep, having to spin for
completion, blocking any other operation.
This change introduces new asynchronous design, sending the IOCBs directly
on request queue and gracefully waiting for their return on response queue.
Returned IOCBs are identified with unified handle space from r292725.
Modified:
head/sys/dev/isp/isp.c
head/sys/dev/isp/isp_library.c
head/sys/dev/isp/ispvar.h
Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c Sat Dec 26 02:31:39 2015 (r292738)
+++ head/sys/dev/isp/isp.c Sat Dec 26 04:26:32 2015 (r292739)
@@ -2348,64 +2348,64 @@ static int
isp_fc_enable_vp(ispsoftc_t *isp, int chan)
{
fcparam *fcp = FCPARAM(isp, chan);
- mbreg_t mbs;
- vp_modify_t *vp;
- uint8_t qe[QENTRY_LEN], *scp;
-
- ISP_MEMZERO(qe, QENTRY_LEN);
- if (FC_SCRATCH_ACQUIRE(isp, chan)) {
- return (EBUSY);
- }
- scp = fcp->isp_scratch;
+ vp_modify_t vp;
+ void *reqp;
+ uint8_t resp[QENTRY_LEN];
/* Build a VP MODIFY command in memory */
- vp = (vp_modify_t *) qe;
- vp->vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
- vp->vp_mod_hdr.rqs_entry_count = 1;
- vp->vp_mod_cnt = 1;
- vp->vp_mod_idx0 = chan;
- vp->vp_mod_cmd = VP_MODIFY_ENA;
- vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
+ ISP_MEMZERO(&vp, sizeof(vp));
+ vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
+ vp.vp_mod_hdr.rqs_entry_count = 1;
+ vp.vp_mod_cnt = 1;
+ vp.vp_mod_idx0 = chan;
+ vp.vp_mod_cmd = VP_MODIFY_ENA;
+ vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
ICB2400_VPOPT_ENA_SNSLOGIN;
- if (fcp->role & ISP_ROLE_INITIATOR) {
- vp->vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
- }
- if ((fcp->role & ISP_ROLE_TARGET) == 0) {
- vp->vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
- }
+ if (fcp->role & ISP_ROLE_INITIATOR)
+ vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
+ if ((fcp->role & ISP_ROLE_TARGET) == 0)
+ vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
- vp->vp_mod_ports[0].loopid = fcp->isp_loopid;
+ vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
- vp->vp_mod_ports[0].options |=
- ICB2400_VPOPT_HARD_ADDRESS;
+ vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
else
- vp->vp_mod_ports[0].options |=
- ICB2400_VPOPT_PREV_ADDRESS;
+ vp.vp_mod_ports[0].options |= ICB2400_VPOPT_PREV_ADDRESS;
}
- MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwpn, fcp->isp_wwpn);
- MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwnn, fcp->isp_wwnn);
- isp_put_vp_modify(isp, vp, (vp_modify_t *) scp);
+ MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
+ MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
- /* Build a EXEC IOCB A64 command that points to the VP MODIFY command */
- MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0);
- mbs.param[1] = QENTRY_LEN;
- mbs.param[2] = DMA_WD1(fcp->isp_scdma);
- mbs.param[3] = DMA_WD0(fcp->isp_scdma);
- mbs.param[6] = DMA_WD3(fcp->isp_scdma);
- mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan);
- isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- FC_SCRATCH_RELEASE(isp, chan);
+ /* Prepare space for response in memory */
+ memset(resp, 0xff, sizeof(resp));
+ vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+ if (vp.vp_mod_hdl == 0) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_MODIFY of Chan %d out of handles", __func__, chan);
return (EIO);
}
- MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
- isp_get_vp_modify(isp, (vp_modify_t *)&scp[QENTRY_LEN], vp);
- FC_SCRATCH_RELEASE(isp, chan);
+ /* Send request and wait for response. */
+ reqp = isp_getrqentry(isp);
+ if (reqp == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan);
+ isp_destroy_handle(isp, vp.vp_mod_hdl);
+ return (EIO);
+ }
+ isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp);
+ ISP_SYNC_REQUEST(isp);
+ if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_MODIFY of Chan %d timed out", __func__, chan);
+ isp_destroy_handle(isp, vp.vp_mod_hdl);
+ return (EIO);
+ }
+ isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp);
- if (vp->vp_mod_status != VP_STS_OK) {
- isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of Chan %d failed with status %d", __func__, chan, vp->vp_mod_status);
+ if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
+ __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
return (EIO);
}
return (0);
@@ -2414,54 +2414,56 @@ isp_fc_enable_vp(ispsoftc_t *isp, int ch
static int
isp_fc_disable_vp(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = FCPARAM(isp, chan);
- mbreg_t mbs;
- vp_ctrl_info_t *vp;
- uint8_t qe[QENTRY_LEN], *scp;
-
- ISP_MEMZERO(qe, QENTRY_LEN);
- if (FC_SCRATCH_ACQUIRE(isp, chan)) {
- return (EBUSY);
- }
- scp = fcp->isp_scratch;
+ vp_ctrl_info_t vp;
+ void *reqp;
+ uint8_t resp[QENTRY_LEN];
/* Build a VP CTRL command in memory */
- vp = (vp_ctrl_info_t *) qe;
- vp->vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
- vp->vp_ctrl_hdr.rqs_entry_count = 1;
+ ISP_MEMZERO(&vp, sizeof(vp));
+ vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
+ vp.vp_ctrl_hdr.rqs_entry_count = 1;
if (ISP_CAP_VP0(isp)) {
- vp->vp_ctrl_status = 1;
+ vp.vp_ctrl_status = 1;
} else {
- vp->vp_ctrl_status = 0;
+ vp.vp_ctrl_status = 0;
chan--; /* VP0 can not be controlled in this case. */
}
- vp->vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
- vp->vp_ctrl_vp_count = 1;
- vp->vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
- isp_put_vp_ctrl_info(isp, vp, (vp_ctrl_info_t *) scp);
-
- /* Build a EXEC IOCB A64 command that points to the VP CTRL command */
- MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0);
- mbs.param[1] = QENTRY_LEN;
- mbs.param[2] = DMA_WD1(fcp->isp_scdma);
- mbs.param[3] = DMA_WD0(fcp->isp_scdma);
- mbs.param[6] = DMA_WD3(fcp->isp_scdma);
- mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan);
- isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- FC_SCRATCH_RELEASE(isp, chan);
+ vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
+ vp.vp_ctrl_vp_count = 1;
+ vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
+
+ /* Prepare space for response in memory */
+ memset(resp, 0xff, sizeof(resp));
+ vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+ if (vp.vp_ctrl_handle == 0) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_CTRL of Chan %d out of handles", __func__, chan);
return (EIO);
}
- MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
- isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)&scp[QENTRY_LEN], vp);
- FC_SCRATCH_RELEASE(isp, chan);
+ /* Send request and wait for response. */
+ reqp = isp_getrqentry(isp);
+ if (reqp == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_CTRL of Chan %d out of rqent", __func__, chan);
+ isp_destroy_handle(isp, vp.vp_ctrl_handle);
+ return (EIO);
+ }
+ isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp);
+ ISP_SYNC_REQUEST(isp);
+ if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) {
+ isp_prt(isp, ISP_LOGERR,
+ "%s: VP_CTRL of Chan %d timed out", __func__, chan);
+ isp_destroy_handle(isp, vp.vp_ctrl_handle);
+ return (EIO);
+ }
+ isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp);
- if (vp->vp_ctrl_status != 0) {
+ if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
isp_prt(isp, ISP_LOGERR,
- "%s: VP_CTRL of Chan %d failed with status %d %d",
- __func__, chan, vp->vp_ctrl_status, vp->vp_ctrl_index_fail);
+ "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
+ __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
+ vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
return (EIO);
}
return (0);
@@ -6123,6 +6125,8 @@ isp_handle_other_response(ispsoftc_t *is
{
isp_ridacq_t rid;
int chan, c;
+ uint32_t hdl;
+ void *ptr;
switch (type) {
case RQSTYPE_STATUS_CONT:
@@ -6164,6 +6168,16 @@ isp_handle_other_response(ispsoftc_t *is
}
}
return (1);
+ case RQSTYPE_VP_MODIFY:
+ case RQSTYPE_VP_CTRL:
+ ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
+ ptr = isp_find_xs(isp, hdl);
+ if (ptr != NULL) {
+ isp_destroy_handle(isp, hdl);
+ memcpy(ptr, hp, QENTRY_LEN);
+ wakeup(ptr);
+ }
+ return (1);
case RQSTYPE_ATIO:
case RQSTYPE_CTIO:
case RQSTYPE_ENABLE_LUN:
Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c Sat Dec 26 02:31:39 2015 (r292738)
+++ head/sys/dev/isp/isp_library.c Sat Dec 26 04:26:32 2015 (r292739)
@@ -572,7 +572,8 @@ isp_clear_commands(ispsoftc_t *isp)
for (tmp = 0; isp->isp_xflist && tmp < isp->isp_maxcmds; tmp++) {
hdp = &isp->isp_xflist[tmp];
- if (ISP_H2HT(hdp->handle) == ISP_HANDLE_INITIATOR) {
+ switch (ISP_H2HT(hdp->handle)) {
+ case ISP_HANDLE_INITIATOR: {
XS_T *xs = hdp->cmd;
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, hdp->handle);
@@ -580,12 +581,13 @@ isp_clear_commands(ispsoftc_t *isp)
} else {
XS_SET_RESID(xs, 0);
}
- hdp->handle = 0;
- hdp->cmd = NULL;
+ isp_destroy_handle(isp, hdp->handle);
XS_SETERR(xs, HBA_BUSRESET);
isp_done(xs);
+ break;
+ }
#ifdef ISP_TARGET_MODE
- } else if (ISP_H2HT(hdp->handle) == ISP_HANDLE_TARGET) {
+ case ISP_HANDLE_TARGET: {
uint8_t local[QENTRY_LEN];
ISP_DMAFREE(isp, hdp->cmd, hdp->handle);
ISP_MEMZERO(local, QENTRY_LEN);
@@ -601,7 +603,13 @@ isp_clear_commands(ispsoftc_t *isp)
ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
}
isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+ break;
+ }
#endif
+ case ISP_HANDLE_CTRL:
+ wakeup(hdp->cmd);
+ isp_destroy_handle(isp, hdp->handle);
+ break;
}
}
#ifdef ISP_TARGET_MODE
Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h Sat Dec 26 02:31:39 2015 (r292738)
+++ head/sys/dev/isp/ispvar.h Sat Dec 26 04:26:32 2015 (r292739)
@@ -315,12 +315,14 @@ typedef struct {
# define ISP_HANDLE_NONE 0
# define ISP_HANDLE_INITIATOR 1
# define ISP_HANDLE_TARGET 2
+# define ISP_HANDLE_CTRL 3
#define ISP_HANDLE_SEQ_MASK 0xffff0000
#define ISP_HANDLE_SEQ_SHIFT 16
#define ISP_H2SEQ(hdl) ((hdl & ISP_HANDLE_SEQ_MASK) >> ISP_HANDLE_SEQ_SHIFT)
#define ISP_VALID_HANDLE(c, hdl) \
((ISP_H2HT(hdl) == ISP_HANDLE_INITIATOR || \
- ISP_H2HT(hdl) == ISP_HANDLE_TARGET) && \
+ ISP_H2HT(hdl) == ISP_HANDLE_TARGET || \
+ ISP_H2HT(hdl) == ISP_HANDLE_CTRL) && \
((hdl) & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \
(hdl) == ((c)->isp_xflist[(hdl) & ISP_HANDLE_CMD_MASK].handle))
#define ISP_BAD_HANDLE_INDEX 0xffffffff
More information about the svn-src-head
mailing list