[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: Vasu Dev <vasu.dev@intel.com> Tested-by: Christof Schmitt <christof.schmitt@de.ibm.com> Tested-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Родитель
14caf44c69
Коммит
4a84067dbf
|
@ -940,10 +940,16 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth);
|
||||||
*/
|
*/
|
||||||
int scsi_track_queue_full(struct scsi_device *sdev, int 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;
|
return 0;
|
||||||
|
|
||||||
sdev->last_queue_full_time = (jiffies >> 4);
|
sdev->last_queue_full_time = jiffies;
|
||||||
if (sdev->last_queue_full_depth != depth) {
|
if (sdev->last_queue_full_depth != depth) {
|
||||||
sdev->last_queue_full_count = 1;
|
sdev->last_queue_full_count = 1;
|
||||||
sdev->last_queue_full_depth = depth;
|
sdev->last_queue_full_depth = depth;
|
||||||
|
|
|
@ -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)
|
static void scsi_handle_queue_full(struct scsi_device *sdev)
|
||||||
{
|
{
|
||||||
struct scsi_host_template *sht = sdev->host->hostt;
|
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)) {
|
switch (status_byte(scmd->result)) {
|
||||||
case GOOD:
|
case GOOD:
|
||||||
|
scsi_handle_queue_ramp_up(scmd->device);
|
||||||
case COMMAND_TERMINATED:
|
case COMMAND_TERMINATED:
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
case CHECK_CONDITION:
|
case CHECK_CONDITION:
|
||||||
|
@ -1425,6 +1462,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
|
||||||
*/
|
*/
|
||||||
return ADD_TO_MLQUEUE;
|
return ADD_TO_MLQUEUE;
|
||||||
case GOOD:
|
case GOOD:
|
||||||
|
scsi_handle_queue_ramp_up(scmd->device);
|
||||||
case COMMAND_TERMINATED:
|
case COMMAND_TERMINATED:
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
case TASK_ABORTED:
|
case TASK_ABORTED:
|
||||||
|
|
|
@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
|
||||||
sdev->model = scsi_null_device_strs;
|
sdev->model = scsi_null_device_strs;
|
||||||
sdev->rev = scsi_null_device_strs;
|
sdev->rev = scsi_null_device_strs;
|
||||||
sdev->host = shost;
|
sdev->host = shost;
|
||||||
|
sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD;
|
||||||
sdev->id = starget->id;
|
sdev->id = starget->id;
|
||||||
sdev->lun = lun;
|
sdev->lun = lun;
|
||||||
sdev->channel = starget->channel;
|
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
|
* Ok, the device is now all set up, we can
|
||||||
* register it and tell the rest of the kernel
|
* register it and tell the rest of the kernel
|
||||||
|
|
|
@ -771,6 +771,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
sdev->max_queue_depth = sdev->queue_depth;
|
||||||
|
|
||||||
return count;
|
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,
|
__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
|
||||||
sdev_store_queue_depth_rw);
|
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
|
static ssize_t
|
||||||
sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
|
sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
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 */
|
/* create queue files, which may be writable, depending on the host */
|
||||||
if (sdev->host->hostt->change_queue_depth)
|
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_depth_rw);
|
||||||
|
error = device_create_file(&sdev->sdev_gendev,
|
||||||
|
&sdev_attr_queue_ramp_up_period);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
|
error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
|
@ -81,11 +81,14 @@ struct scsi_device {
|
||||||
struct list_head starved_entry;
|
struct list_head starved_entry;
|
||||||
struct scsi_cmnd *current_cmnd; /* currently active command */
|
struct scsi_cmnd *current_cmnd; /* currently active command */
|
||||||
unsigned short queue_depth; /* How deep of a queue we want */
|
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_depth; /* These two are used by */
|
||||||
unsigned short last_queue_full_count; /* scsi_track_queue_full() */
|
unsigned short last_queue_full_count; /* scsi_track_queue_full() */
|
||||||
unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
|
unsigned long last_queue_full_time; /* last queue full time */
|
||||||
jiffie count on our counter, they
|
unsigned long queue_ramp_up_period; /* ramp up period in jiffies */
|
||||||
could all be from the same event. */
|
#define SCSI_DEFAULT_RAMP_UP_PERIOD (120 * HZ)
|
||||||
|
|
||||||
|
unsigned long last_queue_ramp_up; /* last queue ramp up time */
|
||||||
|
|
||||||
unsigned int id, lun, channel;
|
unsigned int id, lun, channel;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче