#include "scsi_priv.h"
#include "scsi_logging.h"
+static void scsi_done(struct scsi_cmnd *cmd);
+static int scsi_retry_command(struct scsi_cmnd *cmd);
/*
* Definitions and constants.
"Unknown ",
"RAID ",
"Enclosure ",
+ "Direct-Access-RBC",
};
EXPORT_SYMBOL(scsi_device_types);
* Returns: Pointer to request block.
*/
struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
- int gfp_mask)
+ gfp_t gfp_mask)
{
const int offset = ALIGN(sizeof(struct scsi_request), 4);
const int size = offset + sizeof(struct request);
unsigned int users;
char *name;
unsigned int slab_flags;
- unsigned int gfp_mask;
+ gfp_t gfp_mask;
};
static struct scsi_host_cmd_pool scsi_cmd_pool = {
static DECLARE_MUTEX(host_cmd_pool_mutex);
static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
- int gfp_mask)
+ gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
*
* Returns: The allocated scsi command structure.
*/
-struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
+struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
memset(cmd, 0, sizeof(*cmd));
cmd->device = dev;
- cmd->state = SCSI_STATE_UNUSED;
- cmd->owner = SCSI_OWNER_NOBODY;
init_timer(&cmd->eh_timeout);
INIT_LIST_HEAD(&cmd->list);
spin_lock_irqsave(&dev->list_lock, flags);
} else
put_device(&dev->sdev_gendev);
+ cmd->jiffies_at_alloc = jiffies;
return cmd;
}
EXPORT_SYMBOL(scsi_get_command);
SCSI_LOG_MLQUEUE_BITS);
if (level > 1) {
sdev = cmd->device;
- printk(KERN_INFO "scsi <%d:%d:%d:%d> send ",
- sdev->host->host_no, sdev->channel, sdev->id,
- sdev->lun);
+ sdev_printk(KERN_INFO, sdev, "send ");
if (level > 2)
printk("0x%p ", cmd);
/*
if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
(level > 1)) {
sdev = cmd->device;
- printk(KERN_INFO "scsi <%d:%d:%d:%d> done ",
- sdev->host->host_no, sdev->channel, sdev->id,
- sdev->lun);
+ sdev_printk(KERN_INFO, sdev, "done ");
if (level > 2)
printk("0x%p ", cmd);
/*
* that the device is no longer present */
cmd->result = DID_NO_CONNECT << 16;
atomic_inc(&cmd->device->iorequest_cnt);
- scsi_done(cmd);
+ __scsi_done(cmd);
/* return 0 (because the command has been processed) */
goto out;
}
* We will use a queued command if possible, otherwise we will
* emulate the queuing and calling of completion function ourselves.
*/
-
- cmd->state = SCSI_STATE_QUEUED;
- cmd->owner = SCSI_OWNER_LOWLEVEL;
-
atomic_inc(&cmd->device->iorequest_cnt);
/*
spin_lock_irqsave(host->host_lock, flags);
scsi_cmd_get_serial(host, cmd);
- if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
+ if (unlikely(host->shost_state == SHOST_DEL)) {
cmd->result = (DID_NO_CONNECT << 16);
scsi_done(cmd);
} else {
}
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn) {
- atomic_inc(&cmd->device->iodone_cnt);
- scsi_queue_insert(cmd,
- (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
- rtn : SCSI_MLQUEUE_HOST_BUSY);
+ if (scsi_delete_timer(cmd)) {
+ atomic_inc(&cmd->device->iodone_cnt);
+ scsi_queue_insert(cmd,
+ (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
+ rtn : SCSI_MLQUEUE_HOST_BUSY);
+ }
SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n"));
}
{
sreq->sr_command = cmd;
- cmd->owner = SCSI_OWNER_MIDLEVEL;
cmd->cmd_len = sreq->sr_cmd_len;
cmd->use_sg = sreq->sr_use_sg;
cmd->request = sreq->sr_request;
memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd));
cmd->serial_number = 0;
- cmd->serial_number_at_timeout = 0;
cmd->bufflen = sreq->sr_bufflen;
cmd->buffer = sreq->sr_buffer;
cmd->retries = 0;
/*
* Start the timer ticking.
*/
- cmd->abort_reason = 0;
cmd->result = 0;
SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n"));
*
* This function is interrupt context safe.
*/
-void scsi_done(struct scsi_cmnd *cmd)
+static void scsi_done(struct scsi_cmnd *cmd)
{
/*
* We don't have to worry about this one timing out any more.
* Set the serial numbers back to zero
*/
cmd->serial_number = 0;
- cmd->serial_number_at_timeout = 0;
- cmd->state = SCSI_STATE_BHQUEUE;
- cmd->owner = SCSI_OWNER_BH_HANDLER;
atomic_inc(&cmd->device->iodone_cnt);
if (cmd->result)
while (!list_empty(&local_q)) {
struct scsi_cmnd *cmd = list_entry(local_q.next,
struct scsi_cmnd, eh_entry);
+ /* The longest time any command should be outstanding is the
+ * per command timeout multiplied by the number of retries.
+ *
+ * For a typical command, this is 2.5 minutes */
+ unsigned long wait_for
+ = cmd->allowed * cmd->timeout_per_command;
list_del_init(&cmd->eh_entry);
disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ sdev_printk(KERN_ERR, cmd->device,
+ "timing out command, waited %lus\n",
+ wait_for/HZ);
+ disposition = SUCCESS;
+ }
+
scsi_log_completion(cmd, disposition);
switch (disposition) {
case SUCCESS:
* level drivers should not become re-entrant as a result of
* this.
*/
-int scsi_retry_command(struct scsi_cmnd *cmd)
+static int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
if (SCSI_SENSE_VALID(cmd))
cmd->result |= (DRIVER_SENSE << 24);
- SCSI_LOG_MLCOMPLETE(4, printk("Notifying upper driver of completion "
- "for device %d %x\n", sdev->id, cmd->result));
-
- cmd->owner = SCSI_OWNER_HIGHLEVEL;
- cmd->state = SCSI_STATE_FINISHED;
+ SCSI_LOG_MLCOMPLETE(4, sdev_printk(KERN_INFO, sdev,
+ "Notifying upper driver of completion "
+ "(result %x)\n", cmd->result));
/*
* We can get here with use_sg=0, causing a panic in the upper level
sdev->simple_tags = 1;
break;
default:
- printk(KERN_WARNING "(scsi%d:%d:%d:%d) "
- "scsi_adjust_queue_depth, bad queue type, "
- "disabled\n", sdev->host->host_no,
- sdev->channel, sdev->id, sdev->lun);
+ sdev_printk(KERN_WARNING, sdev,
+ "scsi_adjust_queue_depth, bad queue type, "
+ "disabled\n");
case 0:
sdev->ordered_tags = sdev->simple_tags = 0;
sdev->queue_depth = tags;
list_for_each_safe(lh, lh_sf, &active_list) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_del_init(lh);
- if (recovery) {
- scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD);
- } else {
+ if (recovery &&
+ !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
scmd->result = (DID_ABORT << 16);
scsi_finish_command(scmd);
}