scsi: lpfc: Add support for the CM framework
[linux-2.6-microblaze.git] / drivers / scsi / lpfc / lpfc_nvme.c
index f36294e..73a3568 100644 (file)
@@ -931,6 +931,8 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
        uint32_t code, status, idx;
        uint16_t cid, sqhd, data;
        uint32_t *ptr;
+       uint32_t lat;
+       bool call_done = false;
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        int cpu;
 #endif
@@ -1135,10 +1137,21 @@ out_err:
                freqpriv = nCmd->private;
                freqpriv->nvme_buf = NULL;
                lpfc_ncmd->nvmeCmd = NULL;
-               spin_unlock(&lpfc_ncmd->buf_lock);
+               call_done = true;
+       }
+       spin_unlock(&lpfc_ncmd->buf_lock);
+
+       /* Check if IO qualified for CMF */
+       if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+           nCmd->io_dir == NVMEFC_FCP_READ &&
+           nCmd->payload_length) {
+               /* Used when calculating average latency */
+               lat = ktime_get_ns() - lpfc_ncmd->rx_cmd_start;
+               lpfc_update_cmf_cmpl(phba, lat, nCmd->payload_length, NULL);
+       }
+
+       if (call_done)
                nCmd->done(nCmd);
-       } else
-               spin_unlock(&lpfc_ncmd->buf_lock);
 
        /* Call release with XB=1 to queue the IO into the abort list. */
        lpfc_release_nvme_buf(phba, lpfc_ncmd);
@@ -1212,6 +1225,10 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
                        /* Word 5 */
                        wqe->fcp_iread.rsrvd5 = 0;
 
+                       /* For a CMF Managed port, iod must be zero'ed */
+                       if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
+                               bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
+                                      LPFC_WQE_IOD_NONE);
                        cstat->input_requests++;
                }
        } else {
@@ -1562,6 +1579,19 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
                        expedite = 1;
        }
 
+       /* Check if IO qualifies for CMF */
+       if (phba->cmf_active_mode != LPFC_CFG_OFF &&
+           pnvme_fcreq->io_dir == NVMEFC_FCP_READ &&
+           pnvme_fcreq->payload_length) {
+               ret = lpfc_update_cmf_cmd(phba, pnvme_fcreq->payload_length);
+               if (ret) {
+                       ret = -EBUSY;
+                       goto out_fail;
+               }
+               /* Get start time for IO latency */
+               start = ktime_get_ns();
+       }
+
        /* The node is shared with FCP IO, make sure the IO pending count does
         * not exceed the programmed depth.
         */
@@ -1576,7 +1606,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
                                         ndlp->cmd_qdepth);
                        atomic_inc(&lport->xmt_fcp_qdepth);
                        ret = -EBUSY;
-                       goto out_fail;
+                       goto out_fail1;
                }
        }
 
@@ -1596,7 +1626,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
                                 "idx %d DID %x\n",
                                 lpfc_queue_info->index, ndlp->nlp_DID);
                ret = -EBUSY;
-               goto out_fail;
+               goto out_fail1;
        }
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        if (start) {
@@ -1606,6 +1636,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
                lpfc_ncmd->ts_cmd_start = 0;
        }
 #endif
+       lpfc_ncmd->rx_cmd_start = start;
 
        /*
         * Store the data needed by the driver to issue, abort, and complete
@@ -1687,6 +1718,9 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
        } else
                cstat->control_requests--;
        lpfc_release_nvme_buf(phba, lpfc_ncmd);
+ out_fail1:
+       lpfc_update_cmf_cmpl(phba, LPFC_CGN_NOT_SENT,
+                            pnvme_fcreq->payload_length, NULL);
  out_fail:
        return ret;
 }