#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"
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)
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:
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
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;
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;
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.
case SDEV_CANCEL:
switch (oldstate) {
+ case SDEV_CREATED:
case SDEV_RUNNING:
+ case SDEV_OFFLINE:
break;
default:
goto illegal;
case SDEV_DEL:
switch (oldstate) {
- case SDEV_CREATED:
case SDEV_CANCEL:
- case SDEV_OFFLINE:
break;
default:
goto illegal;