diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-09-07 11:52:04 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-10-13 09:28:57 -0400 |
commit | 977b5a0af6d22a1a0170057c19cde37eeac68acd (patch) | |
tree | 247128ab00aa554eca5366ff8fb3505930729eaf /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | b522d7d42d7ce843885d4c6740c5bd50876a2971 (diff) |
[SCSI] lpfc 8.2.8 v2 : Add sysfs control of target queue depth handling
Added new sysfs attribute lpfc_max_scsicmpl_time. Attribute, when enabled,
will control target queue depth based on I/O completion time.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 72eef7e4a891..7b17f52660b4 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -628,6 +628,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
628 | 628 | ||
629 | lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; | 629 | lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; |
630 | lpfc_cmd->status = pIocbOut->iocb.ulpStatus; | 630 | lpfc_cmd->status = pIocbOut->iocb.ulpStatus; |
631 | atomic_dec(&pnode->cmd_pending); | ||
631 | 632 | ||
632 | if (lpfc_cmd->status) { | 633 | if (lpfc_cmd->status) { |
633 | if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && | 634 | if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && |
@@ -688,6 +689,29 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
688 | 689 | ||
689 | result = cmd->result; | 690 | result = cmd->result; |
690 | sdev = cmd->device; | 691 | sdev = cmd->device; |
692 | if (vport->cfg_max_scsicmpl_time && | ||
693 | time_after(jiffies, lpfc_cmd->start_time + | ||
694 | msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { | ||
695 | spin_lock_irqsave(sdev->host->host_lock, flags); | ||
696 | if ((pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) && | ||
697 | (atomic_read(&pnode->cmd_pending) > LPFC_MIN_TGT_QDEPTH) && | ||
698 | ((cmd->cmnd[0] == READ_10) || (cmd->cmnd[0] == WRITE_10)))) | ||
699 | pnode->cmd_qdepth = atomic_read(&pnode->cmd_pending); | ||
700 | |||
701 | pnode->last_change_time = jiffies; | ||
702 | spin_unlock_irqrestore(sdev->host->host_lock, flags); | ||
703 | } else if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) && | ||
704 | time_after(jiffies, pnode->last_change_time + | ||
705 | msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) { | ||
706 | spin_lock_irqsave(sdev->host->host_lock, flags); | ||
707 | pnode->cmd_qdepth += pnode->cmd_qdepth * | ||
708 | LPFC_TGTQ_RAMPUP_PCENT / 100; | ||
709 | if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH) | ||
710 | pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; | ||
711 | pnode->last_change_time = jiffies; | ||
712 | spin_unlock_irqrestore(sdev->host->host_lock, flags); | ||
713 | } | ||
714 | |||
691 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); | 715 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); |
692 | cmd->scsi_done(cmd); | 716 | cmd->scsi_done(cmd); |
693 | 717 | ||
@@ -1075,6 +1099,8 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1075 | cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); | 1099 | cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); |
1076 | goto out_fail_command; | 1100 | goto out_fail_command; |
1077 | } | 1101 | } |
1102 | if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) | ||
1103 | goto out_host_busy; | ||
1078 | 1104 | ||
1079 | lpfc_cmd = lpfc_get_scsi_buf(phba); | 1105 | lpfc_cmd = lpfc_get_scsi_buf(phba); |
1080 | if (lpfc_cmd == NULL) { | 1106 | if (lpfc_cmd == NULL) { |
@@ -1093,6 +1119,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1093 | lpfc_cmd->pCmd = cmnd; | 1119 | lpfc_cmd->pCmd = cmnd; |
1094 | lpfc_cmd->rdata = rdata; | 1120 | lpfc_cmd->rdata = rdata; |
1095 | lpfc_cmd->timeout = 0; | 1121 | lpfc_cmd->timeout = 0; |
1122 | lpfc_cmd->start_time = jiffies; | ||
1096 | cmnd->host_scribble = (unsigned char *)lpfc_cmd; | 1123 | cmnd->host_scribble = (unsigned char *)lpfc_cmd; |
1097 | cmnd->scsi_done = done; | 1124 | cmnd->scsi_done = done; |
1098 | 1125 | ||
@@ -1102,6 +1129,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1102 | 1129 | ||
1103 | lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); | 1130 | lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); |
1104 | 1131 | ||
1132 | atomic_inc(&ndlp->cmd_pending); | ||
1105 | err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring], | 1133 | err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring], |
1106 | &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); | 1134 | &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); |
1107 | if (err) | 1135 | if (err) |
@@ -1116,6 +1144,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1116 | return 0; | 1144 | return 0; |
1117 | 1145 | ||
1118 | out_host_busy_free_buf: | 1146 | out_host_busy_free_buf: |
1147 | atomic_dec(&ndlp->cmd_pending); | ||
1119 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); | 1148 | lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); |
1120 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 1149 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
1121 | out_host_busy: | 1150 | out_host_busy: |