Commit e02b943b authored by Doug Ledford's avatar Doug Ledford Committed by Linus Torvalds

[PATCH] tcq fixes for the issue on linux-kernel

This does 4 things.  Fixes the oversight James found about cmd_per_lun.
Makes scsi_adjust_queue_depth() implement the usage of tagged that I
described in my email to linux-scsi.  Updates some comments to highlight
things that are going to go away shortly.  Removes the call to
host->select_queue_depths() entirely since drivers that implement this
will try to set SDptr->queue_depth to the desired depth, which in reality
will do nothing but confuse the mid layer since that is now the actual
allocated command counter, so it won't make the mid layer allocate more
commands, it will make the mid layer think more commands have been
allocated.
parent 0b13c1f5
...@@ -1624,11 +1624,40 @@ void scsi_adjust_queue_depth(Scsi_Device *SDpnt, int tagged, int tags) ...@@ -1624,11 +1624,40 @@ void scsi_adjust_queue_depth(Scsi_Device *SDpnt, int tagged, int tags)
/* /*
* refuse to set tagged depth to an unworkable size * refuse to set tagged depth to an unworkable size
*/ */
if(tags == 0) if(tags <= 0)
return; return;
/*
* Limit max queue depth on a single lun to 256 for now. Remember,
* we allocate a struct scsi_command for each of these and keep it
* around forever. Too deep of a depth just wastes memory.
*/
if(tags > 256)
return;
spin_lock_irqsave(&device_request_lock, flags); spin_lock_irqsave(&device_request_lock, flags);
SDpnt->new_queue_depth = tags; SDpnt->new_queue_depth = tags;
SDpnt->tagged_queue = tagged; switch(tagged) {
case MSG_ORDERED_TAG:
SDpnt->ordered_tags = 1;
SDpnt->simple_tags = 1;
break;
case MSG_SIMPLE_TAG:
SDpnt->ordered_tags = 0;
SDpnt->simple_tags = 1;
break;
default:
printk(KERN_WARNING "(scsi%d:%d:%d:%d) "
"scsi_adjust_queue_depth, bad queue type, "
"disabled\n", SDpnt->host->host_no,
SDpnt->channel, SDpnt->id, SDpnt->lun, tagged);
case 0:
SDpnt->ordered_tags = SDpnt->simple_tags = 0;
if(SDpnt->host->cmd_per_lun)
SDpnt->new_queue_depth = SDpnt->host->cmd_per_lun;
else
SDpnt->new_queue_depth = 1;
break;
}
spin_unlock_irqrestore(&device_request_lock, flags); spin_unlock_irqrestore(&device_request_lock, flags);
if(SDpnt->queue_depth == 0) if(SDpnt->queue_depth == 0)
{ {
......
...@@ -605,9 +605,10 @@ struct scsi_device { ...@@ -605,9 +605,10 @@ struct scsi_device {
unsigned wdtr:1; /* Device supports WDTR messages */ unsigned wdtr:1; /* Device supports WDTR messages */
unsigned ppr:1; /* Device supports PPR messages */ unsigned ppr:1; /* Device supports PPR messages */
unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
unsigned tagged_queue:1; /* SCSI-II tagged queuing enabled */ unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags
unsigned simple_tags:1; /* Device supports simple queue tag messages */ instead!!! Please fix your driver now!! */
unsigned ordered_tags:1;/* Device supports ordered queue tag messages */ unsigned simple_tags:1; /* simple queue tag messages are enabled */
unsigned ordered_tags:1;/* ordered queue tag messages are enabled */
unsigned single_lun:1; /* Indicates we should only allow I/O to unsigned single_lun:1; /* Indicates we should only allow I/O to
* one of the luns for the device at a * one of the luns for the device at a
* time. */ * time. */
......
...@@ -424,6 +424,14 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) ...@@ -424,6 +424,14 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
return 0; return 0;
case SCSI_IOCTL_GET_BUS_NUMBER: case SCSI_IOCTL_GET_BUS_NUMBER:
return put_user(dev->host->host_no, (int *) arg); return put_user(dev->host->host_no, (int *) arg);
/*
* The next two ioctls either need to go or need to be changed to
* pass tagged queueing changes through the low level drivers.
* Simply enabling or disabling tagged queueing without the knowledge
* of the low level driver is a *BAD* thing.
*
* Oct. 10, 2002 - Doug Ledford <dledford@redhat.com>
*/
case SCSI_IOCTL_TAGGED_ENABLE: case SCSI_IOCTL_TAGGED_ENABLE:
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
......
...@@ -1477,11 +1477,14 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew, ...@@ -1477,11 +1477,14 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
if (sdt->detect) if (sdt->detect)
sdev->attached += (*sdt->detect) (sdev); sdev->attached += (*sdt->detect) (sdev);
if (sdev->host->hostt->slave_attach != NULL) if (sdev->host->hostt->slave_attach != NULL) {
if (sdev->host->hostt->slave_attach(sdev) != 0) { if (sdev->host->hostt->slave_attach(sdev) != 0) {
printk(KERN_INFO "scsi_add_lun: failed low level driver attach, setting device offline"); printk(KERN_INFO "%s: scsi_add_lun: failed low level driver attach, setting device offline", devname);
sdev->online = FALSE; sdev->online = FALSE;
} }
} else if(sdev->host->cmd_per_lun) {
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
}
if (sdevnew != NULL) if (sdevnew != NULL)
*sdevnew = sdev; *sdevnew = sdev;
...@@ -2017,21 +2020,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel, ...@@ -2017,21 +2020,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
scsi_free_sdev(sdevscan); scsi_free_sdev(sdevscan);
if (res == SCSI_SCAN_LUN_PRESENT) { if (res == SCSI_SCAN_LUN_PRESENT) {
BUG_ON(sdev == NULL); BUG_ON(sdev == NULL);
/*
* FIXME calling select_queue_depths is wrong for adapters
* that modify queue depths of all scsi devices - the
* adapter might change a queue depth (not for this sdev),
* but the mid-layer will not change the queue depth. This
* does not cause an oops, but queue_depth will not match
* the actual queue depth used.
*
* Perhaps use a default queue depth, and allow them to be
* modified at boot/insmod time, and/or via sysctl/ioctl/proc;
* plus have dynamic queue depth adjustment like the
* aic7xxx driver.
*/
if (shost->select_queue_depths != NULL)
(shost->select_queue_depths) (shost, shost->host_queue);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next) for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->init && sdt->dev_noticed) if (sdt->init && sdt->dev_noticed)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment