Commit 82a86da8 authored by James Bottomley's avatar James Bottomley

Merge mulgrave.(none):/home/jejb/BK/scsi-reject-zero-2.5

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents 4dad4b22 aecc28ce
...@@ -209,8 +209,9 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j) ...@@ -209,8 +209,9 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
retval->ehandler = NULL; /* Initial value until the thing starts up. */ retval->ehandler = NULL; /* Initial value until the thing starts up. */
retval->eh_notify = NULL; /* Who we notify when we exit. */ retval->eh_notify = NULL; /* Who we notify when we exit. */
retval->max_host_blocked = tpnt->max_host_blocked ? tpnt->max_host_blocked : SCSI_DEFAULT_HOST_BLOCKED;
retval->host_blocked = FALSE; retval->host_blocked = 0;
retval->host_self_blocked = FALSE; retval->host_self_blocked = FALSE;
#ifdef DEBUG #ifdef DEBUG
......
...@@ -297,6 +297,19 @@ typedef struct SHT ...@@ -297,6 +297,19 @@ typedef struct SHT
*/ */
char *proc_name; char *proc_name;
/*
* countdown for host blocking with no commands outstanding
*/
unsigned int max_host_blocked;
/*
* Default value for the blocking. If the queue is empty, host_blocked
* counts down in the request_fn until it restarts host operations as
* zero is reached.
*
* FIXME: This should probably be a value in the template */
#define SCSI_DEFAULT_HOST_BLOCKED 7
} Scsi_Host_Template; } Scsi_Host_Template;
/* /*
...@@ -394,11 +407,6 @@ struct Scsi_Host ...@@ -394,11 +407,6 @@ struct Scsi_Host
unsigned highmem_io:1; unsigned highmem_io:1;
unsigned use_blk_tcq:1; unsigned use_blk_tcq:1;
/*
* Host has rejected a command because it was busy.
*/
unsigned host_blocked:1;
/* /*
* Host has requested that no further requests come through for the * Host has requested that no further requests come through for the
* time being. * time being.
...@@ -417,6 +425,16 @@ struct Scsi_Host ...@@ -417,6 +425,16 @@ struct Scsi_Host
*/ */
unsigned some_device_starved:1; unsigned some_device_starved:1;
/*
* Host has rejected a command because it was busy.
*/
unsigned int host_blocked;
/*
* Value host_blocked counts down from
*/
unsigned int max_host_blocked;
void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *); void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
/* /*
......
...@@ -616,25 +616,17 @@ static int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) ...@@ -616,25 +616,17 @@ static int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
* If the host/device isn't busy, assume that something actually * If the host/device isn't busy, assume that something actually
* completed, and that we should be able to queue a command now. * completed, and that we should be able to queue a command now.
* *
* Note that there is an implicit assumption that every host can * Note that the prior mid-layer assumption that any host could
* always queue at least one command. If a host is inactive and * always queue at least one command is now broken. The mid-layer
* cannot queue any commands, I don't see how things could * will implement a user specifiable stall (see
* possibly work anyways. * scsi_host.max_host_blocked and scsi_device.max_device_blocked)
* if a command is requeued with no other commands outstanding
* either for the device or for the host.
*/ */
if (reason == SCSI_MLQUEUE_HOST_BUSY) { if (reason == SCSI_MLQUEUE_HOST_BUSY) {
if (host->host_busy == 0) { host->host_blocked = host->max_host_blocked;
if (scsi_retry_command(cmd) == 0) {
return 0;
}
}
host->host_blocked = TRUE;
} else { } else {
if (cmd->device->device_busy == 0) { cmd->device->device_blocked = cmd->device->max_device_blocked;
if (scsi_retry_command(cmd) == 0) {
return 0;
}
}
cmd->device->device_blocked = TRUE;
} }
/* /*
...@@ -793,7 +785,7 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt) ...@@ -793,7 +785,7 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
spin_unlock_irqrestore(host->host_lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
if (rtn != 0) { if (rtn != 0) {
scsi_delete_timer(SCpnt); scsi_delete_timer(SCpnt);
scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY); scsi_mlqueue_insert(SCpnt, rtn == SCSI_MLQUEUE_DEVICE_BUSY ? rtn : SCSI_MLQUEUE_HOST_BUSY);
SCSI_LOG_MLQUEUE(3, SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n")); printk("queuecommand : request rejected\n"));
} }
...@@ -1396,8 +1388,8 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt) ...@@ -1396,8 +1388,8 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
* for both the queue full condition on a device, and for a * for both the queue full condition on a device, and for a
* host full condition on the host. * host full condition on the host.
*/ */
host->host_blocked = FALSE; host->host_blocked = 0;
device->device_blocked = FALSE; device->device_blocked = 0;
/* /*
* If we have valid sense information, then some kind of recovery * If we have valid sense information, then some kind of recovery
......
...@@ -611,12 +611,18 @@ struct scsi_device { ...@@ -611,12 +611,18 @@ struct scsi_device {
* this device */ * this device */
unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
* because we did a bus reset. */ * because we did a bus reset. */
unsigned device_blocked:1; /* Device returned QUEUE_FULL. */
unsigned ten:1; /* support ten byte read / write */ unsigned ten:1; /* support ten byte read / write */
unsigned remap:1; /* support remapping */ unsigned remap:1; /* support remapping */
unsigned starved:1; /* unable to process commands because unsigned starved:1; /* unable to process commands because
host busy */ host busy */
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
unsigned int max_device_blocked; /* what device_blocked counts down from */
/* default value if the device doesn't override */
#define SCSI_DEFAULT_DEVICE_BLOCKED 3
// Flag to allow revalidate to succeed in sd_open // Flag to allow revalidate to succeed in sd_open
int allow_revalidate; int allow_revalidate;
struct device sdev_driverfs_dev; struct device sdev_driverfs_dev;
......
...@@ -1341,6 +1341,13 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd) ...@@ -1341,6 +1341,13 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
* the case of trying to send too many commands to a * the case of trying to send too many commands to a
* tagged queueing device. * tagged queueing device.
*/ */
case BUSY:
/*
* device can't talk to us at the moment. Should only
* occur (SAM-3) when the task queue is empty, so will cause
* the empty queue handling to trigger a stall in the
* device.
*/
return ADD_TO_MLQUEUE; return ADD_TO_MLQUEUE;
case GOOD: case GOOD:
case COMMAND_TERMINATED: case COMMAND_TERMINATED:
...@@ -1358,8 +1365,6 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd) ...@@ -1358,8 +1365,6 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
* who knows? FIXME(eric) * who knows? FIXME(eric)
*/ */
return SUCCESS; return SUCCESS;
case BUSY:
goto maybe_retry;
case RESERVATION_CONFLICT: case RESERVATION_CONFLICT:
printk("scsi%d (%d,%d,%d) : reservation conflict\n", printk("scsi%d (%d,%d,%d) : reservation conflict\n",
......
...@@ -754,6 +754,24 @@ void scsi_request_fn(request_queue_t * q) ...@@ -754,6 +754,24 @@ void scsi_request_fn(request_queue_t * q)
if (SHpnt->in_recovery || blk_queue_plugged(q)) if (SHpnt->in_recovery || blk_queue_plugged(q))
return; return;
if(SHpnt->host_busy == 0 && SHpnt->host_blocked) {
/* unblock after host_blocked iterates to zero */
if(--SHpnt->host_blocked == 0) {
SCSI_LOG_MLQUEUE(3, printk("scsi%d unblocking host at zero depth\n", SHpnt->host_no));
} else {
blk_plug_device(q);
break;
}
}
if(SDpnt->device_busy == 0 && SDpnt->device_blocked) {
/* unblock after device_blocked iterates to zero */
if(--SDpnt->device_blocked == 0) {
SCSI_LOG_MLQUEUE(3, printk("scsi%d (%d:%d) unblocking device at zero depth\n", SHpnt->host_no, SDpnt->id, SDpnt->lun));
} else {
blk_plug_device(q);
break;
}
}
/* /*
* If the device cannot accept another request, then quit. * If the device cannot accept another request, then quit.
*/ */
......
...@@ -1461,6 +1461,10 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew, ...@@ -1461,6 +1461,10 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
if (*bflags & BLIST_SINGLELUN) if (*bflags & BLIST_SINGLELUN)
sdev->single_lun = 1; sdev->single_lun = 1;
/* if the device needs this changing, it may do so in the detect
* function */
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
for (sdt = scsi_devicelist; sdt; sdt = sdt->next) for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detect) if (sdt->detect)
sdev->attached += (*sdt->detect) (sdev); sdev->attached += (*sdt->detect) (sdev);
......
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