This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / scsi / scsi_lib.c
index 48b4717..ac16f21 100644 (file)
 #include <linux/init.h>
 #include <linux/pci.h>
 
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
-#include "scsi.h"
+#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -255,7 +259,6 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
        sreq->sr_request->rq_status = RQ_SCSI_BUSY;
        scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
                        timeout, retries);
-       generic_unplug_device(sreq->sr_device->request_queue);
        wait_for_completion(&wait);
        sreq->sr_request->waiting = NULL;
        if (sreq->sr_request->rq_status != RQ_SCSI_DONE)
@@ -838,8 +841,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
                        printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
                               cmd->device->host->host_no, (int) cmd->device->channel,
                               (int) cmd->device->id, (int) cmd->device->lun);
-                       print_command(cmd->data_cmnd);
-                       print_sense("", cmd);
+                       __scsi_print_command(cmd->data_cmnd);
+                       scsi_print_sense("", cmd);
                        cmd = scsi_end_request(cmd, 0, block_bytes, 1);
                        return;
                default:
@@ -863,7 +866,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
                       cmd->device->lun, result);
 
                if (driver_byte(result) & DRIVER_SENSE)
-                       print_sense("", cmd);
+                       scsi_print_sense("", cmd);
                /*
                 * Mark a single buffer as not uptodate.  Queue the remainder.
                 * We sometimes get this cruft in the event that a medium error
@@ -951,6 +954,22 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
        return BLKPREP_KILL;
 }
 
+static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+                              sector_t *error_sector)
+{
+       struct scsi_device *sdev = q->queuedata;
+       struct scsi_driver *drv;
+
+       if (sdev->sdev_state != SDEV_RUNNING)
+               return -ENXIO;
+
+       drv = *(struct scsi_driver **) disk->private_data;
+       if (drv->issue_flush)
+               return drv->issue_flush(&sdev->sdev_gendev, error_sector);
+
+       return -EOPNOTSUPP;
+}
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
        struct scsi_device *sdev = q->queuedata;
@@ -1332,7 +1351,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
        blk_queue_max_sectors(q, shost->max_sectors);
        blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
        blk_queue_segment_boundary(q, shost->dma_boundary);
+       blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
        return q;
@@ -1552,6 +1572,34 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
        return ret;
 }
 
+int
+scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
+{
+       struct scsi_request *sreq;
+       char cmd[] = {
+               TEST_UNIT_READY, 0, 0, 0, 0, 0,
+       };
+       int result;
+       
+       sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+       if (!sreq)
+               return -ENOMEM;
+
+               sreq->sr_data_direction = DMA_NONE;
+        scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+
+       if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
+           (sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION &&
+           sdev->removable) {
+               sdev->changed = 1;
+               sreq->sr_result = 0;
+       }
+       result = sreq->sr_result;
+       scsi_release_request(sreq);
+       return result;
+}
+EXPORT_SYMBOL(scsi_test_unit_ready);
+
 /**
  *     scsi_device_set_state - Take the given device through the device
  *             state model.
@@ -1610,7 +1658,9 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
 
        case SDEV_CANCEL:
                switch (oldstate) {
+               case SDEV_CREATED:
                case SDEV_RUNNING:
+               case SDEV_OFFLINE:
                        break;
                default:
                        goto illegal;
@@ -1619,9 +1669,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
 
        case SDEV_DEL:
                switch (oldstate) {
-               case SDEV_CREATED:
                case SDEV_CANCEL:
-               case SDEV_OFFLINE:
                        break;
                default:
                        goto illegal;