diff options
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r-- | drivers/scsi/sr.c | 59 |
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; |