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

Commit 70e75889 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by Kyle Yan
Browse files

scsi: add option to override the command timeout



Some platforms might be very slow and command completion may take
much longer than default scsi command timeouts.
SCSI Read/Write command timeout can be changed by blk_queue_rq_timeout()
but there is no option to override timeout for rest of the scsi commands.
This change allows the LLD to override the default scsi command timeout
for all scsi commands (except read/write).

Change-Id: Ia36c1b1ca30f86844003d7187e84bec9ed8e22a9
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent 877ec81d
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -202,7 +202,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
	req->sense = sense;
	req->sense_len = 0;
	req->retries = retries;
	if (likely(!sdev->timeout_override))
		req->timeout = timeout;
	else
		req->timeout = sdev->timeout_override;

	req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT;

	/*
@@ -2176,6 +2180,33 @@ void scsi_unblock_requests(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(scsi_unblock_requests);

/*
 * Function:    scsi_set_cmd_timeout_override()
 *
 * Purpose:     Utility function used by low-level drivers to override
		timeout for the scsi commands.
 *
 * Arguments:   sdev       - scsi device in question
 *		timeout	   - timeout in jiffies
 *
 * Returns:     Nothing
 *
 * Lock status: No locks are assumed held.
 *
 * Notes:	Some platforms might be very slow and command completion may
 *		take much longer than default scsi command timeouts.
 *		SCSI Read/Write command timeout can be changed by
 *		blk_queue_rq_timeout() but there is no option to override
 *		timeout for rest of the scsi commands. This function would
 *		would allow this.
 */
void scsi_set_cmd_timeout_override(struct scsi_device *sdev,
				   unsigned int timeout)
{
	sdev->timeout_override = timeout;
}
EXPORT_SYMBOL(scsi_set_cmd_timeout_override);

int __init scsi_init_queue(void)
{
	scsi_sdb_cache = kmem_cache_create("scsi_data_buffer",
+8 −2
Original line number Diff line number Diff line
@@ -766,7 +766,10 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
	}

	rq->completion_data = page;
	if (likely(!sdp->timeout_override))
		rq->timeout = SD_TIMEOUT;
	else
		rq->timeout = sdp->timeout_override;

	cmd->transfersize = len;
	cmd->allowed = SD_MAX_RETRIES;
@@ -846,7 +849,10 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
	sector >>= ilog2(sdp->sector_size) - 9;
	nr_sectors >>= ilog2(sdp->sector_size) - 9;

	if (likely(!sdp->timeout_override))
		rq->timeout = SD_WRITE_SAME_TIMEOUT;
	else
		rq->timeout = sdp->timeout_override;

	if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
		cmd->cmd_len = 16;
+5 −1
Original line number Diff line number Diff line
@@ -807,7 +807,11 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
	else
		at_head = 1;

	if (likely(!sdp->device->timeout_override))
		srp->rq->timeout = timeout;
	else
		srp->rq->timeout = sdp->device->timeout_override;

	kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */
	blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
			      srp->rq, at_head, sg_rq_end_io);
+4 −0
Original line number Diff line number Diff line
@@ -186,6 +186,8 @@ struct scsi_device {

#define SCSI_DEFAULT_AUTOSUSPEND_DELAY  -1
	int autosuspend_delay;
	/* If non-zero, use timeout (in jiffies) for all commands */
	unsigned int timeout_override;

	atomic_t disk_events_disable_depth; /* disable depth for disk events */

@@ -431,6 +433,8 @@ extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev);
extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t);
extern int scsi_vpd_tpg_id(struct scsi_device *, int *);
extern void scsi_set_cmd_timeout_override(struct scsi_device *sdev,
					  unsigned int timeout);

#ifdef CONFIG_PM
extern int scsi_autopm_get_device(struct scsi_device *);