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>
This commit is contained in:
Родитель
9a6e6400a9
Коммит
e05fe29248
|
@ -2023,6 +2023,8 @@ typedef struct fc_port {
|
||||||
unsigned long last_ramp_up;
|
unsigned long last_ramp_up;
|
||||||
|
|
||||||
uint16_t port_id;
|
uint16_t port_id;
|
||||||
|
|
||||||
|
unsigned long retry_delay_timestamp;
|
||||||
} fc_port_t;
|
} fc_port_t;
|
||||||
|
|
||||||
#include "qla_mr.h"
|
#include "qla_mr.h"
|
||||||
|
|
|
@ -567,7 +567,7 @@ struct sts_entry_24xx {
|
||||||
#define SF_TRANSFERRED_DATA BIT_11
|
#define SF_TRANSFERRED_DATA BIT_11
|
||||||
#define SF_FCP_RSP_DMA BIT_0
|
#define SF_FCP_RSP_DMA BIT_0
|
||||||
|
|
||||||
uint16_t reserved_2;
|
uint16_t retry_delay;
|
||||||
uint16_t scsi_status; /* SCSI status. */
|
uint16_t scsi_status; /* SCSI status. */
|
||||||
#define SS_CONFIRMATION_REQ BIT_12
|
#define SS_CONFIRMATION_REQ BIT_12
|
||||||
|
|
||||||
|
|
|
@ -279,3 +279,11 @@ qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
|
||||||
complete(&ha->mbx_intr_comp);
|
complete(&ha->mbx_intr_comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
|
||||||
|
{
|
||||||
|
if (retry_delay)
|
||||||
|
fcport->retry_delay_timestamp = jiffies +
|
||||||
|
(retry_delay * HZ / 10);
|
||||||
|
}
|
||||||
|
|
|
@ -1983,6 +1983,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
||||||
int logit = 1;
|
int logit = 1;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
uint16_t state_flags = 0;
|
uint16_t state_flags = 0;
|
||||||
|
uint16_t retry_delay = 0;
|
||||||
|
|
||||||
sts = (sts_entry_t *) pkt;
|
sts = (sts_entry_t *) pkt;
|
||||||
sts24 = (struct sts_entry_24xx *) pkt;
|
sts24 = (struct sts_entry_24xx *) pkt;
|
||||||
|
@ -2076,6 +2077,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
||||||
host_to_fcp_swap(sts24->data, sizeof(sts24->data));
|
host_to_fcp_swap(sts24->data, sizeof(sts24->data));
|
||||||
ox_id = le16_to_cpu(sts24->ox_id);
|
ox_id = le16_to_cpu(sts24->ox_id);
|
||||||
par_sense_len = sizeof(sts24->data);
|
par_sense_len = sizeof(sts24->data);
|
||||||
|
/* Valid values of the retry delay timer are 0x1-0xffef */
|
||||||
|
if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1)
|
||||||
|
retry_delay = sts24->retry_delay;
|
||||||
} else {
|
} else {
|
||||||
if (scsi_status & SS_SENSE_LEN_VALID)
|
if (scsi_status & SS_SENSE_LEN_VALID)
|
||||||
sense_len = le16_to_cpu(sts->req_sense_length);
|
sense_len = le16_to_cpu(sts->req_sense_length);
|
||||||
|
@ -2109,6 +2113,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
||||||
scsi_status & SS_RESIDUAL_OVER)
|
scsi_status & SS_RESIDUAL_OVER)
|
||||||
comp_status = CS_DATA_OVERRUN;
|
comp_status = CS_DATA_OVERRUN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check retry_delay_timer value if we receive a busy or
|
||||||
|
* queue full.
|
||||||
|
*/
|
||||||
|
if (lscsi_status == SAM_STAT_TASK_SET_FULL ||
|
||||||
|
lscsi_status == SAM_STAT_BUSY)
|
||||||
|
qla2x00_set_retry_delay_timestamp(fcport, retry_delay);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Based on Host and scsi status generate status code for Linux
|
* Based on Host and scsi status generate status code for Linux
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -731,6 +731,15 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||||
goto qc24_target_busy;
|
goto qc24_target_busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return target busy if we've received a non-zero retry_delay_timer
|
||||||
|
* in a FCP_RSP.
|
||||||
|
*/
|
||||||
|
if (time_after(jiffies, fcport->retry_delay_timestamp))
|
||||||
|
fcport->retry_delay_timestamp = 0;
|
||||||
|
else
|
||||||
|
goto qc24_target_busy;
|
||||||
|
|
||||||
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
|
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
|
||||||
if (!sp)
|
if (!sp)
|
||||||
goto qc24_host_busy;
|
goto qc24_host_busy;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче