aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChad Dupuis <chad.dupuis@qlogic.com>2014-09-25 05:16:59 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-25 08:25:04 -0400
commite05fe2924892a6c3c23dc818e94ce80dbceb86b1 (patch)
tree1e12e068afb1bf09dd8bc0db09b1ff0945dbb47f
parent9a6e6400a9bef4a7fb11ccddf932e1868f566a73 (diff)
qla2xxx: Honor FCP_RSP retry delay timer field.
Parse the retry delay timer field from the FCP response data and if: - It is not zero - The SCSI status is busy or queue full return SCSI_MLQUEUE_TARGET_BUSY for the number of milliseconds specified in the retry delay timer field. Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c9
5 files changed, 32 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index d9daad7db6ce..d529510bbc6c 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2023,6 +2023,8 @@ typedef struct fc_port {
2023 unsigned long last_ramp_up; 2023 unsigned long last_ramp_up;
2024 2024
2025 uint16_t port_id; 2025 uint16_t port_id;
2026
2027 unsigned long retry_delay_timestamp;
2026} fc_port_t; 2028} fc_port_t;
2027 2029
2028#include "qla_mr.h" 2030#include "qla_mr.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 7f2e1c71cc31..42bb357bf56b 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -567,7 +567,7 @@ struct sts_entry_24xx {
567#define SF_TRANSFERRED_DATA BIT_11 567#define SF_TRANSFERRED_DATA BIT_11
568#define SF_FCP_RSP_DMA BIT_0 568#define SF_FCP_RSP_DMA BIT_0
569 569
570 uint16_t reserved_2; 570 uint16_t retry_delay;
571 uint16_t scsi_status; /* SCSI status. */ 571 uint16_t scsi_status; /* SCSI status. */
572#define SS_CONFIRMATION_REQ BIT_12 572#define SS_CONFIRMATION_REQ BIT_12
573 573
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index b3b1d6fc2d6c..fee9eb7c8a60 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -279,3 +279,11 @@ qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
279 complete(&ha->mbx_intr_comp); 279 complete(&ha->mbx_intr_comp);
280 } 280 }
281} 281}
282
283static inline void
284qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
285{
286 if (retry_delay)
287 fcport->retry_delay_timestamp = jiffies +
288 (retry_delay * HZ / 10);
289}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 550ffdf0bf17..f15f87e1abd8 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1983,6 +1983,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
1983 int logit = 1; 1983 int logit = 1;
1984 int res = 0; 1984 int res = 0;
1985 uint16_t state_flags = 0; 1985 uint16_t state_flags = 0;
1986 uint16_t retry_delay = 0;
1986 1987
1987 sts = (sts_entry_t *) pkt; 1988 sts = (sts_entry_t *) pkt;
1988 sts24 = (struct sts_entry_24xx *) pkt; 1989 sts24 = (struct sts_entry_24xx *) pkt;
@@ -2076,6 +2077,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
2076 host_to_fcp_swap(sts24->data, sizeof(sts24->data)); 2077 host_to_fcp_swap(sts24->data, sizeof(sts24->data));
2077 ox_id = le16_to_cpu(sts24->ox_id); 2078 ox_id = le16_to_cpu(sts24->ox_id);
2078 par_sense_len = sizeof(sts24->data); 2079 par_sense_len = sizeof(sts24->data);
2080 /* Valid values of the retry delay timer are 0x1-0xffef */
2081 if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1)
2082 retry_delay = sts24->retry_delay;
2079 } else { 2083 } else {
2080 if (scsi_status & SS_SENSE_LEN_VALID) 2084 if (scsi_status & SS_SENSE_LEN_VALID)
2081 sense_len = le16_to_cpu(sts->req_sense_length); 2085 sense_len = le16_to_cpu(sts->req_sense_length);
@@ -2110,6 +2114,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
2110 comp_status = CS_DATA_OVERRUN; 2114 comp_status = CS_DATA_OVERRUN;
2111 2115
2112 /* 2116 /*
2117 * Check retry_delay_timer value if we receive a busy or
2118 * queue full.
2119 */
2120 if (lscsi_status == SAM_STAT_TASK_SET_FULL ||
2121 lscsi_status == SAM_STAT_BUSY)
2122 qla2x00_set_retry_delay_timestamp(fcport, retry_delay);
2123
2124 /*
2113 * Based on Host and scsi status generate status code for Linux 2125 * Based on Host and scsi status generate status code for Linux
2114 */ 2126 */
2115 switch (comp_status) { 2127 switch (comp_status) {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e742890d5d1b..daabf8c9c298 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -731,6 +731,15 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
731 goto qc24_target_busy; 731 goto qc24_target_busy;
732 } 732 }
733 733
734 /*
735 * Return target busy if we've received a non-zero retry_delay_timer
736 * in a FCP_RSP.
737 */
738 if (time_after(jiffies, fcport->retry_delay_timestamp))
739 fcport->retry_delay_timestamp = 0;
740 else
741 goto qc24_target_busy;
742
734 sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); 743 sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
735 if (!sp) 744 if (!sp)
736 goto qc24_host_busy; 745 goto qc24_host_busy;