summaryrefslogtreecommitdiff
path: root/drivers/scsi/sr.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2007-08-04 10:06:25 -0500
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:49:30 -0400
commit7f9a6bc4e9d59e7fcf03ed23f60cd81ca5d80b65 (patch)
treef2cceb87e2b6c9a66c66a8c8ceeb20bad09bb6fa /drivers/scsi/sr.c
parentd3849d512fb0ca1e369e3efcaec910a949f55f62 (diff)
downloadlwn-7f9a6bc4e9d59e7fcf03ed23f60cd81ca5d80b65.tar.gz
lwn-7f9a6bc4e9d59e7fcf03ed23f60cd81ca5d80b65.zip
[SCSI] move ULD attachment into the prep function
One of the intents of the block prep function was to allow ULDs to use it for preprocessing. The original SCSI model was to have a single prep function and add a pointer indirect filter to build the necessary commands. This patch reverses that, does away with the init_command field of the scsi_driver structure and makes ULDs attach directly to the prep function instead. The value is really that it allows us to begin to separate the ULDs from the SCSI mid layer (as long as they don't use any core functions---which is hard at the moment---a ULD doesn't even need SCSI to bind). Acked-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r--drivers/scsi/sr.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 902eb11ffe8a..a0c4e13d4dab 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -78,7 +78,6 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
-static int sr_init_command(struct scsi_cmnd *);
static struct scsi_driver sr_template = {
.owner = THIS_MODULE,
@@ -87,7 +86,6 @@ static struct scsi_driver sr_template = {
.probe = sr_probe,
.remove = sr_remove,
},
- .init_command = sr_init_command,
};
static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG];
@@ -296,19 +294,39 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
scsi_io_completion(SCpnt, good_bytes);
}
-static int sr_init_command(struct scsi_cmnd * SCpnt)
+static int sr_prep_fn(struct request_queue *q, struct request *rq)
{
int block=0, this_count, s_size, timeout = SR_TIMEOUT;
- struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk);
+ struct scsi_cd *cd;
+ struct scsi_cmnd *SCpnt;
+ struct scsi_device *sdp = q->queuedata;
+ int ret;
+
+ if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
+ ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+ goto out;
+ } else if (rq->cmd_type != REQ_TYPE_FS) {
+ ret = BLKPREP_KILL;
+ goto out;
+ }
+ ret = scsi_setup_fs_cmnd(sdp, rq);
+ if (ret != BLKPREP_OK)
+ goto out;
+ SCpnt = rq->special;
+ cd = scsi_cd(rq->rq_disk);
+
+ /* from here on until we're complete, any goto out
+ * is used for a killable error condition */
+ ret = BLKPREP_KILL;
SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n",
cd->disk->disk_name, block));
if (!cd->device || !scsi_device_online(cd->device)) {
SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
- SCpnt->request->nr_sectors));
+ rq->nr_sectors));
SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
- return 0;
+ goto out;
}
if (cd->device->changed) {
@@ -316,7 +334,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
* quietly refuse to do anything to a changed disc until the
* changed bit has been reset
*/
- return 0;
+ goto out;
}
/*
@@ -333,21 +351,21 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
if (s_size != 512 && s_size != 1024 && s_size != 2048) {
scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size);
- return 0;
+ goto out;
}
- if (rq_data_dir(SCpnt->request) == WRITE) {
+ if (rq_data_dir(rq) == WRITE) {
if (!cd->device->writeable)
- return 0;
+ goto out;
SCpnt->cmnd[0] = WRITE_10;
SCpnt->sc_data_direction = DMA_TO_DEVICE;
cd->cdi.media_written = 1;
- } else if (rq_data_dir(SCpnt->request) == READ) {
+ } else if (rq_data_dir(rq) == READ) {
SCpnt->cmnd[0] = READ_10;
SCpnt->sc_data_direction = DMA_FROM_DEVICE;
} else {
- blk_dump_rq_flags(SCpnt->request, "Unknown sr command");
- return 0;
+ blk_dump_rq_flags(rq, "Unknown sr command");
+ goto out;
}
{
@@ -368,10 +386,10 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
/*
* request doesn't start on hw block boundary, add scatter pads
*/
- if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) ||
+ if (((unsigned int)rq->sector % (s_size >> 9)) ||
(SCpnt->request_bufflen % s_size)) {
scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
- return 0;
+ goto out;
}
this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
@@ -379,12 +397,12 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
cd->cdi.name,
- (rq_data_dir(SCpnt->request) == WRITE) ?
+ (rq_data_dir(rq) == WRITE) ?
"writing" : "reading",
- this_count, SCpnt->request->nr_sectors));
+ this_count, rq->nr_sectors));
SCpnt->cmnd[1] = 0;
- block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
+ block = (unsigned int)rq->sector / (s_size >> 9);
if (this_count > 0xffff) {
this_count = 0xffff;
@@ -419,7 +437,9 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
* This indicates that the command is ready from our end to be
* queued.
*/
- return 1;
+ ret = BLKPREP_OK;
+ out:
+ return scsi_prep_return(q, rq, ret);
}
static int sr_block_open(struct inode *inode, struct file *file)
@@ -590,6 +610,7 @@ static int sr_probe(struct device *dev)
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities(cd);
+ blk_queue_prep_rq(sdev->request_queue, sr_prep_fn);
sr_vendor_init(cd);
disk->driverfs_dev = &sdev->sdev_gendev;