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

Commit 4a84067d authored by Vasu Dev's avatar Vasu Dev Committed by James Bottomley
Browse files

[SCSI] add queue_depth ramp up code



Current FC HBA queue_depth ramp up code depends on last queue
full time. The sdev already  has last_queue_full_time field to
track last queue full time but stored value is truncated by
last four bits.

So this patch updates last_queue_full_time without truncating
last 4 bits to store full value and then updates its only
current usages in scsi_track_queue_full to ignore last four bits
to keep current usages same while also use this field
in added ramp up code.

Adds scsi_handle_queue_ramp_up to ramp up queue_depth on
successful completion of IO. The scsi_handle_queue_ramp_up will
do ramp up on all luns of a target, just same as ramp down done
on all luns on a target.

The ramp up is skipped in case the change_queue_depth is not
supported by LLD or already reached to added max_queue_depth.

Updates added max_queue_depth on every new update to default
queue_depth value.

The ramp up is also skipped if lapsed time since either last
queue ramp up or down is less than LLD specified
queue_ramp_up_period.

Adds queue_ramp_up_period to sysfs but only if change_queue_depth
is supported since ramp up and queue_ramp_up_period is needed only
in case change_queue_depth is supported first.

Initializes queue_ramp_up_period to 120HZ jiffies as initial
default value, it is same as used in existing lpfc and qla2xxx.

-v2
 Combined all ramp code into this single patch.

-v3
 Moves max_queue_depth initialization after slave_configure is
called from after slave_alloc calling done. Also adjusted
max_queue_depth check to skip ramp up if current queue_depth
is >= max_queue_depth.

-v4
 Changes sdev->queue_ramp_up_period unit to ms when using sysfs i/f
to store or show its value.

Signed-off-by: default avatarVasu Dev <vasu.dev@intel.com>
Tested-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Tested-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 14caf44c
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -940,10 +940,16 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth);
 */
int scsi_track_queue_full(struct scsi_device *sdev, int depth)
{
	if ((jiffies >> 4) == sdev->last_queue_full_time)

	/*
	 * Don't let QUEUE_FULLs on the same
	 * jiffies count, they could all be from
	 * same event.
	 */
	if ((jiffies >> 4) == (sdev->last_queue_full_time >> 4))
		return 0;

	sdev->last_queue_full_time = (jiffies >> 4);
	sdev->last_queue_full_time = jiffies;
	if (sdev->last_queue_full_depth != depth) {
		sdev->last_queue_full_count = 1;
		sdev->last_queue_full_depth = depth;
+38 −0
Original line number Diff line number Diff line
@@ -331,6 +331,42 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
	}
}

static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
{
	struct scsi_host_template *sht = sdev->host->hostt;
	struct scsi_device *tmp_sdev;

	if (!sht->change_queue_depth ||
	    sdev->queue_depth >= sdev->max_queue_depth)
		return;

	if (time_before(jiffies,
	    sdev->last_queue_ramp_up + sdev->queue_ramp_up_period))
		return;

	if (time_before(jiffies,
	    sdev->last_queue_full_time + sdev->queue_ramp_up_period))
		return;

	/*
	 * Walk all devices of a target and do
	 * ramp up on them.
	 */
	shost_for_each_device(tmp_sdev, sdev->host) {
		if (tmp_sdev->channel != sdev->channel ||
		    tmp_sdev->id != sdev->id ||
		    tmp_sdev->queue_depth == sdev->max_queue_depth)
			continue;
		/*
		 * call back into LLD to increase queue_depth by one
		 * with ramp up reason code.
		 */
		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1,
					SCSI_QDEPTH_RAMP_UP);
		sdev->last_queue_ramp_up = jiffies;
	}
}

static void scsi_handle_queue_full(struct scsi_device *sdev)
{
	struct scsi_host_template *sht = sdev->host->hostt;
@@ -393,6 +429,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
	 */
	switch (status_byte(scmd->result)) {
	case GOOD:
		scsi_handle_queue_ramp_up(scmd->device);
	case COMMAND_TERMINATED:
		return SUCCESS;
	case CHECK_CONDITION:
@@ -1425,6 +1462,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
		 */
		return ADD_TO_MLQUEUE;
	case GOOD:
		scsi_handle_queue_ramp_up(scmd->device);
	case COMMAND_TERMINATED:
		return SUCCESS;
	case TASK_ABORTED:
+3 −0
Original line number Diff line number Diff line
@@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
	sdev->model = scsi_null_device_strs;
	sdev->rev = scsi_null_device_strs;
	sdev->host = shost;
	sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD;
	sdev->id = starget->id;
	sdev->lun = lun;
	sdev->channel = starget->channel;
@@ -941,6 +942,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
		}
	}

	sdev->max_queue_depth = sdev->queue_depth;

	/*
	 * Ok, the device is now all set up, we can
	 * register it and tell the rest of the kernel
+39 −2
Original line number Diff line number Diff line
@@ -771,6 +771,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
	if (retval < 0)
		return retval;

	sdev->max_queue_depth = sdev->queue_depth;

	return count;
}

@@ -778,6 +780,37 @@ static struct device_attribute sdev_attr_queue_depth_rw =
	__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
	       sdev_store_queue_depth_rw);

static ssize_t
sdev_show_queue_ramp_up_period(struct device *dev,
			       struct device_attribute *attr,
			       char *buf)
{
	struct scsi_device *sdev;
	sdev = to_scsi_device(dev);
	return snprintf(buf, 20, "%u\n",
			jiffies_to_msecs(sdev->queue_ramp_up_period));
}

static ssize_t
sdev_store_queue_ramp_up_period(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct scsi_device *sdev = to_scsi_device(dev);
	unsigned long period;

	if (strict_strtoul(buf, 10, &period))
		return -EINVAL;

	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
	return period;
}

static struct device_attribute sdev_attr_queue_ramp_up_period =
	__ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
	       sdev_show_queue_ramp_up_period,
	       sdev_store_queue_ramp_up_period);

static ssize_t
sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
			 const char *buf, size_t count)
@@ -866,8 +899,12 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
	}

	/* create queue files, which may be writable, depending on the host */
	if (sdev->host->hostt->change_queue_depth)
		error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
	if (sdev->host->hostt->change_queue_depth) {
		error = device_create_file(&sdev->sdev_gendev,
					   &sdev_attr_queue_depth_rw);
		error = device_create_file(&sdev->sdev_gendev,
					   &sdev_attr_queue_ramp_up_period);
	}
	else
		error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
	if (error) {
+6 −3
Original line number Diff line number Diff line
@@ -81,11 +81,14 @@ struct scsi_device {
	struct list_head starved_entry;
	struct scsi_cmnd *current_cmnd;	/* currently active command */
	unsigned short queue_depth;	/* How deep of a queue we want */
	unsigned short max_queue_depth;	/* max queue depth */
	unsigned short last_queue_full_depth; /* These two are used by */
	unsigned short last_queue_full_count; /* scsi_track_queue_full() */
	unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
					   jiffie count on our counter, they
					   could all be from the same event. */
	unsigned long last_queue_full_time;	/* last queue full time */
	unsigned long queue_ramp_up_period;	/* ramp up period in jiffies */
#define SCSI_DEFAULT_RAMP_UP_PERIOD	(120 * HZ)

	unsigned long last_queue_ramp_up;	/* last queue ramp up time */

	unsigned int id, lun, channel;