aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-08-17 16:24:38 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:46 -0400
commitf0c0a376d0fcd4c5579ecf5e95f88387cba85211 (patch)
tree16b97ab71a22106cb1e5c1a177ab6c8103fe5a48 /drivers/scsi/scsi.c
parent4480f15b3306f43bbb0310d461142b4e897ca45b (diff)
[SCSI] Add helper code so transport classes/driver can control queueing (v3)
SCSI-ml manages the queueing limits for the device and host, but does not do so at the target level. However something something similar can come in userful when a driver is transitioning a transport object to the the blocked state, becuase at that time we do not want to queue io and we do not want the queuecommand to be called again. The patch adds code similar to the exisiting SCSI_ML_*BUSY handlers. You can now return SCSI_MLQUEUE_TARGET_BUSY when we hit a transport level queueing issue like the hw cannot allocate some resource at the iscsi session/connection level, or the target has temporarily closed or shrunk the queueing window, or if we are transitioning to the blocked state. bnx2i, when they rework their firmware according to netdev developers requests, will also need to be able to limit queueing at this level. bnx2i will hook into libiscsi, but will allocate a scsi host per netdevice/hba, so unlike pure software iscsi/iser which is allocating a host per session, it cannot set the scsi_host->can_queue and return SCSI_MLQUEUE_HOST_BUSY to reflect queueing limits on the transport. The iscsi class/driver can also set a scsi_target->can_queue value which reflects the max commands the driver/class can support. For iscsi this reflects the number of commands we can support for each session due to session/connection hw limits, driver limits, and to also reflect the session/targets's queueing window. Changes: v1 - initial patch. v2 - Fix scsi_run_queue handling of multiple blocked targets. Previously we would break from the main loop if a device was added back on the starved list. We now run over the list and check if any target is blocked. v3 - Rediff for scsi-misc. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r--drivers/scsi/scsi.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2ac3cb2b9081..f8b79d401d58 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -754,8 +754,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
754 } 754 }
755 spin_unlock_irqrestore(host->host_lock, flags); 755 spin_unlock_irqrestore(host->host_lock, flags);
756 if (rtn) { 756 if (rtn) {
757 scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? 757 if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
758 rtn : SCSI_MLQUEUE_HOST_BUSY); 758 rtn != SCSI_MLQUEUE_TARGET_BUSY)
759 rtn = SCSI_MLQUEUE_HOST_BUSY;
760
761 scsi_queue_insert(cmd, rtn);
762
759 SCSI_LOG_MLQUEUE(3, 763 SCSI_LOG_MLQUEUE(3,
760 printk("queuecommand : request rejected\n")); 764 printk("queuecommand : request rejected\n"));
761 } 765 }
@@ -800,6 +804,7 @@ static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
800void scsi_finish_command(struct scsi_cmnd *cmd) 804void scsi_finish_command(struct scsi_cmnd *cmd)
801{ 805{
802 struct scsi_device *sdev = cmd->device; 806 struct scsi_device *sdev = cmd->device;
807 struct scsi_target *starget = scsi_target(sdev);
803 struct Scsi_Host *shost = sdev->host; 808 struct Scsi_Host *shost = sdev->host;
804 struct scsi_driver *drv; 809 struct scsi_driver *drv;
805 unsigned int good_bytes; 810 unsigned int good_bytes;
@@ -815,6 +820,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
815 * XXX(hch): What about locking? 820 * XXX(hch): What about locking?
816 */ 821 */
817 shost->host_blocked = 0; 822 shost->host_blocked = 0;
823 starget->target_blocked = 0;
818 sdev->device_blocked = 0; 824 sdev->device_blocked = 0;
819 825
820 /* 826 /*