Author: mav
Date: Wed Dec 30 11:50:52 2015
New Revision: 292922
URL: https://svnweb.freebsd.org/changeset/base/292922

Log:
  MFC r292739: 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:
  stable/10/sys/dev/isp/isp.c
  stable/10/sys/dev/isp/isp_library.c
  stable/10/sys/dev/isp/ispvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c Wed Dec 30 11:49:48 2015        (r292921)
+++ stable/10/sys/dev/isp/isp.c Wed Dec 30 11:50:52 2015        (r292922)
@@ -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: stable/10/sys/dev/isp/isp_library.c
==============================================================================
--- stable/10/sys/dev/isp/isp_library.c Wed Dec 30 11:49:48 2015        
(r292921)
+++ stable/10/sys/dev/isp/isp_library.c Wed Dec 30 11:50:52 2015        
(r292922)
@@ -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: stable/10/sys/dev/isp/ispvar.h
==============================================================================
--- stable/10/sys/dev/isp/ispvar.h      Wed Dec 30 11:49:48 2015        
(r292921)
+++ stable/10/sys/dev/isp/ispvar.h      Wed Dec 30 11:50:52 2015        
(r292922)
@@ -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
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to