diff options
author | Tej Parkash <tej.parkash@qlogic.com> | 2013-03-07 05:43:13 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-04-10 14:49:34 -0400 |
commit | a24058f9c2368568aed14593b8a63706408547da (patch) | |
tree | ecd9fcb537f353aa6eaa3938592dd42b73f40d2c | |
parent | 33338e31839fe45fa794bcc227d292dd7fab786c (diff) |
[SCSI] qla4xxx: Fixed request queue count manipulation on response path
Issue:
Request queue count holds the information about free space in request queue
which has to be manipulated based on request in and out pointer.
But in driver response path, this count was incremented unconditionally,
which could move req_in pointer beyond req_out pointer.
This scenario leads fw hang during IO.
Solution:
Request queue count manipulation has to be done in IO path only, keeping
req_in and req_out pointer two IOCB count away
Signed-off-by: Tej Parkash <tej.parkash@qlogic.com>
Signed-off-by: Shyam Sundar <shyam.sundar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 15 |
3 files changed, 2 insertions, 17 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 982293edf02c..22706f66266f 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -224,8 +224,6 @@ void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha, | |||
224 | int qla4_83xx_isp_reset(struct scsi_qla_host *ha); | 224 | int qla4_83xx_isp_reset(struct scsi_qla_host *ha); |
225 | void qla4_83xx_queue_iocb(struct scsi_qla_host *ha); | 225 | void qla4_83xx_queue_iocb(struct scsi_qla_host *ha); |
226 | void qla4_83xx_complete_iocb(struct scsi_qla_host *ha); | 226 | void qla4_83xx_complete_iocb(struct scsi_qla_host *ha); |
227 | uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha); | ||
228 | uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); | ||
229 | uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr); | 227 | uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr); |
230 | void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val); | 228 | void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val); |
231 | int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr, | 229 | int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr, |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index e02a884b950b..7bef448e2946 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -396,7 +396,6 @@ static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha, | |||
396 | 396 | ||
397 | task_data = task->dd_data; | 397 | task_data = task->dd_data; |
398 | memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status)); | 398 | memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status)); |
399 | ha->req_q_count += task_data->iocb_req_cnt; | ||
400 | ha->iocb_cnt -= task_data->iocb_req_cnt; | 399 | ha->iocb_cnt -= task_data->iocb_req_cnt; |
401 | queue_work(ha->task_wq, &task_data->task_work); | 400 | queue_work(ha->task_wq, &task_data->task_work); |
402 | } | 401 | } |
@@ -416,7 +415,6 @@ static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha, | |||
416 | return mrb; | 415 | return mrb; |
417 | 416 | ||
418 | /* update counters */ | 417 | /* update counters */ |
419 | ha->req_q_count += mrb->iocb_cnt; | ||
420 | ha->iocb_cnt -= mrb->iocb_cnt; | 418 | ha->iocb_cnt -= mrb->iocb_cnt; |
421 | 419 | ||
422 | return mrb; | 420 | return mrb; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ade1ba6b3451..a6ce04d1adae 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -3751,8 +3751,8 @@ static struct isp_operations qla4_83xx_isp_ops = { | |||
3751 | .reset_firmware = qla4_8xxx_stop_firmware, | 3751 | .reset_firmware = qla4_8xxx_stop_firmware, |
3752 | .queue_iocb = qla4_83xx_queue_iocb, | 3752 | .queue_iocb = qla4_83xx_queue_iocb, |
3753 | .complete_iocb = qla4_83xx_complete_iocb, | 3753 | .complete_iocb = qla4_83xx_complete_iocb, |
3754 | .rd_shdw_req_q_out = qla4_83xx_rd_shdw_req_q_out, | 3754 | .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, |
3755 | .rd_shdw_rsp_q_in = qla4_83xx_rd_shdw_rsp_q_in, | 3755 | .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, |
3756 | .get_sys_info = qla4_8xxx_get_sys_info, | 3756 | .get_sys_info = qla4_8xxx_get_sys_info, |
3757 | .rd_reg_direct = qla4_83xx_rd_reg, | 3757 | .rd_reg_direct = qla4_83xx_rd_reg, |
3758 | .wr_reg_direct = qla4_83xx_wr_reg, | 3758 | .wr_reg_direct = qla4_83xx_wr_reg, |
@@ -3775,11 +3775,6 @@ uint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | |||
3775 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out)); | 3775 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out)); |
3776 | } | 3776 | } |
3777 | 3777 | ||
3778 | uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
3779 | { | ||
3780 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->req_q_out)); | ||
3781 | } | ||
3782 | |||
3783 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | 3778 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) |
3784 | { | 3779 | { |
3785 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); | 3780 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); |
@@ -3790,11 +3785,6 @@ uint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | |||
3790 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in)); | 3785 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in)); |
3791 | } | 3786 | } |
3792 | 3787 | ||
3793 | uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
3794 | { | ||
3795 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->rsp_q_in)); | ||
3796 | } | ||
3797 | |||
3798 | static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf) | 3788 | static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf) |
3799 | { | 3789 | { |
3800 | struct scsi_qla_host *ha = data; | 3790 | struct scsi_qla_host *ha = data; |
@@ -5683,7 +5673,6 @@ struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, | |||
5683 | 5673 | ||
5684 | /* update counters */ | 5674 | /* update counters */ |
5685 | if (srb->flags & SRB_DMA_VALID) { | 5675 | if (srb->flags & SRB_DMA_VALID) { |
5686 | ha->req_q_count += srb->iocb_cnt; | ||
5687 | ha->iocb_cnt -= srb->iocb_cnt; | 5676 | ha->iocb_cnt -= srb->iocb_cnt; |
5688 | if (srb->cmd) | 5677 | if (srb->cmd) |
5689 | srb->cmd->host_scribble = | 5678 | srb->cmd->host_scribble = |