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)
retval->ehandler = NULL; /* Initial value until the thing starts up. */
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;
#ifdef DEBUG
......
......@@ -297,6 +297,19 @@ typedef struct SHT
*/
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;
/*
......@@ -394,11 +407,6 @@ struct Scsi_Host
unsigned highmem_io: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
* time being.
......@@ -417,6 +425,16 @@ struct Scsi_Host
*/
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 *);
/*
......
......@@ -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
* completed, and that we should be able to queue a command now.
*
* Note that there is an implicit assumption that every host can
* always queue at least one command. If a host is inactive and
* cannot queue any commands, I don't see how things could
* possibly work anyways.
* Note that the prior mid-layer assumption that any host could
* always queue at least one command is now broken. The mid-layer
* will implement a user specifiable stall (see
* 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 (host->host_busy == 0) {
if (scsi_retry_command(cmd) == 0) {
return 0;
}
}
host->host_blocked = TRUE;
host->host_blocked = host->max_host_blocked;
} else {
if (cmd->device->device_busy == 0) {
if (scsi_retry_command(cmd) == 0) {
return 0;
}
}
cmd->device->device_blocked = TRUE;
cmd->device->device_blocked = cmd->device->max_device_blocked;
}
/*
......@@ -793,7 +785,7 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn != 0) {
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,
printk("queuecommand : request rejected\n"));
}
......@@ -1396,8 +1388,8 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
* for both the queue full condition on a device, and for a
* host full condition on the host.
*/
host->host_blocked = FALSE;
device->device_blocked = FALSE;
host->host_blocked = 0;
device->device_blocked = 0;
/*
* If we have valid sense information, then some kind of recovery
......
......@@ -611,12 +611,18 @@ struct scsi_device {
* this device */
unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
* because we did a bus reset. */
unsigned device_blocked:1; /* Device returned QUEUE_FULL. */
unsigned ten:1; /* support ten byte read / write */
unsigned remap:1; /* support remapping */
unsigned starved:1; /* unable to process commands because
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
int allow_revalidate;
struct device sdev_driverfs_dev;
......
......@@ -1341,6 +1341,13 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
* the case of trying to send too many commands to a
* 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;
case GOOD:
case COMMAND_TERMINATED:
......@@ -1358,8 +1365,6 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
* who knows? FIXME(eric)
*/
return SUCCESS;
case BUSY:
goto maybe_retry;
case RESERVATION_CONFLICT:
printk("scsi%d (%d,%d,%d) : reservation conflict\n",
......
......@@ -754,6 +754,24 @@ void scsi_request_fn(request_queue_t * q)
if (SHpnt->in_recovery || blk_queue_plugged(q))
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.
*/
......
......@@ -1461,6 +1461,10 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
if (*bflags & BLIST_SINGLELUN)
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)
if (sdt->detect)
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