Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e05fe292 authored by Chad Dupuis's avatar Chad Dupuis Committed by Christoph Hellwig
Browse files

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: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarSaurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 9a6e6400
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2023,6 +2023,8 @@ typedef struct fc_port {
	unsigned long last_ramp_up;

	uint16_t port_id;

	unsigned long retry_delay_timestamp;
} fc_port_t;

#include "qla_mr.h"
+1 −1
Original line number Diff line number Diff line
@@ -567,7 +567,7 @@ struct sts_entry_24xx {
#define SF_TRANSFERRED_DATA	BIT_11
#define SF_FCP_RSP_DMA		BIT_0

	uint16_t reserved_2;
	uint16_t retry_delay;
	uint16_t scsi_status;		/* SCSI status. */
#define SS_CONFIRMATION_REQ		BIT_12

+8 −0
Original line number Diff line number Diff line
@@ -279,3 +279,11 @@ qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
		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);
}
+12 −0
Original line number Diff line number Diff line
@@ -1983,6 +1983,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
	int logit = 1;
	int res = 0;
	uint16_t state_flags = 0;
	uint16_t retry_delay = 0;

	sts = (sts_entry_t *) 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));
		ox_id = le16_to_cpu(sts24->ox_id);
		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 {
		if (scsi_status & SS_SENSE_LEN_VALID)
			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)
		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
	 */
+9 −0
Original line number Diff line number Diff line
@@ -731,6 +731,15 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
		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);
	if (!sp)
		goto qc24_host_busy;