diff options
| author | Vasu Dev <vasu.dev@intel.com> | 2009-10-22 18:46:33 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:00:44 -0500 |
| commit | 4a84067dbfce436b81779e585bf712b02ceee552 (patch) | |
| tree | f787d413a11c6564ad4440d0a245f56d0e6b73bf | |
| parent | 14caf44c69184ed72d46a2f883311daf27a4192f (diff) | |
[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>
| -rw-r--r-- | drivers/scsi/scsi.c | 10 | ||||
| -rw-r--r-- | drivers/scsi/scsi_error.c | 38 | ||||
| -rw-r--r-- | drivers/scsi/scsi_scan.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/scsi_sysfs.c | 41 | ||||
| -rw-r--r-- | include/scsi/scsi_device.h | 9 |
5 files changed, 94 insertions, 7 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index dd098cad337b..a60da5555577 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -940,10 +940,16 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth); | |||
| 940 | */ | 940 | */ |
| 941 | int scsi_track_queue_full(struct scsi_device *sdev, int depth) | 941 | int scsi_track_queue_full(struct scsi_device *sdev, int depth) |
| 942 | { | 942 | { |
| 943 | if ((jiffies >> 4) == sdev->last_queue_full_time) | 943 | |
| 944 | /* | ||
| 945 | * Don't let QUEUE_FULLs on the same | ||
| 946 | * jiffies count, they could all be from | ||
| 947 | * same event. | ||
| 948 | */ | ||
| 949 | if ((jiffies >> 4) == (sdev->last_queue_full_time >> 4)) | ||
| 944 | return 0; | 950 | return 0; |
| 945 | 951 | ||
| 946 | sdev->last_queue_full_time = (jiffies >> 4); | 952 | sdev->last_queue_full_time = jiffies; |
| 947 | if (sdev->last_queue_full_depth != depth) { | 953 | if (sdev->last_queue_full_depth != depth) { |
| 948 | sdev->last_queue_full_count = 1; | 954 | sdev->last_queue_full_count = 1; |
| 949 | sdev->last_queue_full_depth = depth; | 955 | sdev->last_queue_full_depth = depth; |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 7b1e20fee906..08ed506e6059 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -331,6 +331,42 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) | ||
| 335 | { | ||
| 336 | struct scsi_host_template *sht = sdev->host->hostt; | ||
| 337 | struct scsi_device *tmp_sdev; | ||
| 338 | |||
| 339 | if (!sht->change_queue_depth || | ||
| 340 | sdev->queue_depth >= sdev->max_queue_depth) | ||
| 341 | return; | ||
| 342 | |||
| 343 | if (time_before(jiffies, | ||
| 344 | sdev->last_queue_ramp_up + sdev->queue_ramp_up_period)) | ||
| 345 | return; | ||
| 346 | |||
| 347 | if (time_before(jiffies, | ||
| 348 | sdev->last_queue_full_time + sdev->queue_ramp_up_period)) | ||
| 349 | return; | ||
| 350 | |||
| 351 | /* | ||
| 352 | * Walk all devices of a target and do | ||
| 353 | * ramp up on them. | ||
| 354 | */ | ||
| 355 | shost_for_each_device(tmp_sdev, sdev->host) { | ||
| 356 | if (tmp_sdev->channel != sdev->channel || | ||
| 357 | tmp_sdev->id != sdev->id || | ||
| 358 | tmp_sdev->queue_depth == sdev->max_queue_depth) | ||
| 359 | continue; | ||
| 360 | /* | ||
| 361 | * call back into LLD to increase queue_depth by one | ||
| 362 | * with ramp up reason code. | ||
| 363 | */ | ||
| 364 | sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1, | ||
| 365 | SCSI_QDEPTH_RAMP_UP); | ||
| 366 | sdev->last_queue_ramp_up = jiffies; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 334 | static void scsi_handle_queue_full(struct scsi_device *sdev) | 370 | static void scsi_handle_queue_full(struct scsi_device *sdev) |
| 335 | { | 371 | { |
| 336 | struct scsi_host_template *sht = sdev->host->hostt; | 372 | struct scsi_host_template *sht = sdev->host->hostt; |
| @@ -393,6 +429,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) | |||
| 393 | */ | 429 | */ |
| 394 | switch (status_byte(scmd->result)) { | 430 | switch (status_byte(scmd->result)) { |
| 395 | case GOOD: | 431 | case GOOD: |
| 432 | scsi_handle_queue_ramp_up(scmd->device); | ||
| 396 | case COMMAND_TERMINATED: | 433 | case COMMAND_TERMINATED: |
| 397 | return SUCCESS; | 434 | return SUCCESS; |
| 398 | case CHECK_CONDITION: | 435 | case CHECK_CONDITION: |
| @@ -1425,6 +1462,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
| 1425 | */ | 1462 | */ |
| 1426 | return ADD_TO_MLQUEUE; | 1463 | return ADD_TO_MLQUEUE; |
| 1427 | case GOOD: | 1464 | case GOOD: |
| 1465 | scsi_handle_queue_ramp_up(scmd->device); | ||
| 1428 | case COMMAND_TERMINATED: | 1466 | case COMMAND_TERMINATED: |
| 1429 | return SUCCESS; | 1467 | return SUCCESS; |
| 1430 | case TASK_ABORTED: | 1468 | case TASK_ABORTED: |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 0547a7f44d42..50526fa207e5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, | |||
| 251 | sdev->model = scsi_null_device_strs; | 251 | sdev->model = scsi_null_device_strs; |
| 252 | sdev->rev = scsi_null_device_strs; | 252 | sdev->rev = scsi_null_device_strs; |
| 253 | sdev->host = shost; | 253 | sdev->host = shost; |
| 254 | sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD; | ||
| 254 | sdev->id = starget->id; | 255 | sdev->id = starget->id; |
| 255 | sdev->lun = lun; | 256 | sdev->lun = lun; |
| 256 | sdev->channel = starget->channel; | 257 | sdev->channel = starget->channel; |
| @@ -941,6 +942,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
| 941 | } | 942 | } |
| 942 | } | 943 | } |
| 943 | 944 | ||
| 945 | sdev->max_queue_depth = sdev->queue_depth; | ||
| 946 | |||
| 944 | /* | 947 | /* |
| 945 | * Ok, the device is now all set up, we can | 948 | * Ok, the device is now all set up, we can |
| 946 | * register it and tell the rest of the kernel | 949 | * register it and tell the rest of the kernel |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a48782866b22..758598ff3b90 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -771,6 +771,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, | |||
| 771 | if (retval < 0) | 771 | if (retval < 0) |
| 772 | return retval; | 772 | return retval; |
| 773 | 773 | ||
| 774 | sdev->max_queue_depth = sdev->queue_depth; | ||
| 775 | |||
| 774 | return count; | 776 | return count; |
| 775 | } | 777 | } |
| 776 | 778 | ||
| @@ -779,6 +781,37 @@ static struct device_attribute sdev_attr_queue_depth_rw = | |||
| 779 | sdev_store_queue_depth_rw); | 781 | sdev_store_queue_depth_rw); |
| 780 | 782 | ||
| 781 | static ssize_t | 783 | static ssize_t |
| 784 | sdev_show_queue_ramp_up_period(struct device *dev, | ||
| 785 | struct device_attribute *attr, | ||
| 786 | char *buf) | ||
| 787 | { | ||
| 788 | struct scsi_device *sdev; | ||
| 789 | sdev = to_scsi_device(dev); | ||
| 790 | return snprintf(buf, 20, "%u\n", | ||
| 791 | jiffies_to_msecs(sdev->queue_ramp_up_period)); | ||
| 792 | } | ||
| 793 | |||
| 794 | static ssize_t | ||
| 795 | sdev_store_queue_ramp_up_period(struct device *dev, | ||
| 796 | struct device_attribute *attr, | ||
| 797 | const char *buf, size_t count) | ||
| 798 | { | ||
| 799 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 800 | unsigned long period; | ||
| 801 | |||
| 802 | if (strict_strtoul(buf, 10, &period)) | ||
| 803 | return -EINVAL; | ||
| 804 | |||
| 805 | sdev->queue_ramp_up_period = msecs_to_jiffies(period); | ||
| 806 | return period; | ||
| 807 | } | ||
| 808 | |||
| 809 | static struct device_attribute sdev_attr_queue_ramp_up_period = | ||
| 810 | __ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, | ||
| 811 | sdev_show_queue_ramp_up_period, | ||
| 812 | sdev_store_queue_ramp_up_period); | ||
| 813 | |||
| 814 | static ssize_t | ||
| 782 | sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, | 815 | sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, |
| 783 | const char *buf, size_t count) | 816 | const char *buf, size_t count) |
| 784 | { | 817 | { |
| @@ -866,8 +899,12 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
| 866 | } | 899 | } |
| 867 | 900 | ||
| 868 | /* create queue files, which may be writable, depending on the host */ | 901 | /* create queue files, which may be writable, depending on the host */ |
| 869 | if (sdev->host->hostt->change_queue_depth) | 902 | if (sdev->host->hostt->change_queue_depth) { |
| 870 | error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw); | 903 | error = device_create_file(&sdev->sdev_gendev, |
| 904 | &sdev_attr_queue_depth_rw); | ||
| 905 | error = device_create_file(&sdev->sdev_gendev, | ||
| 906 | &sdev_attr_queue_ramp_up_period); | ||
| 907 | } | ||
| 871 | else | 908 | else |
| 872 | error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth); | 909 | error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth); |
| 873 | if (error) { | 910 | if (error) { |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9af48cbf0036..92c4c3bd916d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
| @@ -81,11 +81,14 @@ struct scsi_device { | |||
| 81 | struct list_head starved_entry; | 81 | struct list_head starved_entry; |
| 82 | struct scsi_cmnd *current_cmnd; /* currently active command */ | 82 | struct scsi_cmnd *current_cmnd; /* currently active command */ |
| 83 | unsigned short queue_depth; /* How deep of a queue we want */ | 83 | unsigned short queue_depth; /* How deep of a queue we want */ |
| 84 | unsigned short max_queue_depth; /* max queue depth */ | ||
| 84 | unsigned short last_queue_full_depth; /* These two are used by */ | 85 | unsigned short last_queue_full_depth; /* These two are used by */ |
| 85 | unsigned short last_queue_full_count; /* scsi_track_queue_full() */ | 86 | unsigned short last_queue_full_count; /* scsi_track_queue_full() */ |
| 86 | unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same | 87 | unsigned long last_queue_full_time; /* last queue full time */ |
| 87 | jiffie count on our counter, they | 88 | unsigned long queue_ramp_up_period; /* ramp up period in jiffies */ |
| 88 | could all be from the same event. */ | 89 | #define SCSI_DEFAULT_RAMP_UP_PERIOD (120 * HZ) |
| 90 | |||
| 91 | unsigned long last_queue_ramp_up; /* last queue ramp up time */ | ||
| 89 | 92 | ||
| 90 | unsigned int id, lun, channel; | 93 | unsigned int id, lun, channel; |
| 91 | 94 | ||
