diff options
author | Matthew Wilcox <matthew@wil.cx> | 2007-09-25 20:42:04 +0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 22:52:46 +0400 |
commit | 6f5391c283d7fdcf24bf40786ea79061919d1e1d (patch) | |
tree | 32ee9abddf9879445792019e1c03bcd28ce6bd4f | |
parent | 687d2bc4877081a44c41b5b312e012cc69edda53 (diff) | |
download | linux-6f5391c283d7fdcf24bf40786ea79061919d1e1d.tar.xz |
[SCSI] Get rid of scsi_cmnd->done
The ULD ->done callback moves into the scsi_driver. By moving the call
to scsi_io_completion() from scsi_blk_pc_done() to scsi_finish_command(),
we can eliminate the latter entirely. By returning 'good_bytes' from
the ->done callback (rather than invoking scsi_io_completion()), we can
stop exporting scsi_io_completion().
Also move the prototypes from sd.h to sd.c as they're all internal anyway.
Rename sd_rw_intr to sd_done and rw_intr to sr_done.
Inspired-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/scsi.c | 20 | ||||
-rw-r--r-- | drivers/scsi/scsi_error.c | 1 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 14 | ||||
-rw-r--r-- | drivers/scsi/scsi_priv.h | 1 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 28 | ||||
-rw-r--r-- | drivers/scsi/sr.c | 21 | ||||
-rw-r--r-- | include/scsi/scsi_cmnd.h | 2 | ||||
-rw-r--r-- | include/scsi/scsi_driver.h | 1 | ||||
-rw-r--r-- | include/scsi/sd.h | 13 |
9 files changed, 43 insertions, 58 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 07a7c2a70a3f..192948822455 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -59,6 +59,7 @@ #include <scsi/scsi_cmnd.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/scsi_tcq.h> @@ -367,9 +368,8 @@ void scsi_log_send(struct scsi_cmnd *cmd) scsi_print_command(cmd); if (level > 3) { printk(KERN_INFO "buffer = 0x%p, bufflen = %d," - " done = 0x%p, queuecommand 0x%p\n", + " queuecommand 0x%p\n", scsi_sglist(cmd), scsi_bufflen(cmd), - cmd->done, cmd->device->host->hostt->queuecommand); } @@ -654,6 +654,12 @@ void __scsi_done(struct scsi_cmnd *cmd) blk_complete_request(rq); } +/* Move this to a header if it becomes more generally useful */ +static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) +{ + return *(struct scsi_driver **)cmd->request->rq_disk->private_data; +} + /* * Function: scsi_finish_command * @@ -665,6 +671,8 @@ void scsi_finish_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; + struct scsi_driver *drv; + unsigned int good_bytes; scsi_device_unbusy(sdev); @@ -690,7 +698,13 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "Notifying upper driver of completion " "(result %x)\n", cmd->result)); - cmd->done(cmd); + good_bytes = cmd->request_bufflen; + if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { + drv = scsi_cmd_to_driver(cmd); + if (drv->done) + good_bytes = drv->done(cmd); + } + scsi_io_completion(cmd, good_bytes); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 44e6721ddea6..f49feb9351d0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1671,7 +1671,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); scmd->scsi_done = scsi_reset_provider_done_command; - scmd->done = NULL; scmd->request_buffer = NULL; scmd->request_bufflen = 0; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 86fd3abe731a..fac34293bef7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -982,7 +982,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } scsi_end_request(cmd, 0, this_count, !result); } -EXPORT_SYMBOL(scsi_io_completion); /* * Function: scsi_init_io() @@ -1063,18 +1062,6 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -static void scsi_blk_pc_done(struct scsi_cmnd *cmd) -{ - BUG_ON(!blk_pc_request(cmd->request)); - /* - * This will complete the whole command with uptodate=1 so - * as far as the block layer is concerned the command completed - * successfully. Since this is a REQ_BLOCK_PC command the - * caller should check the request's errors value - */ - scsi_io_completion(cmd, cmd->request_bufflen); -} - int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; @@ -1124,7 +1111,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; - cmd->done = scsi_blk_pc_done; return BLKPREP_OK; } EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index ee8efe849bf4..eff005951895 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -68,6 +68,7 @@ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_device_unbusy(struct scsi_device *sdev); extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); extern void scsi_next_command(struct scsi_cmnd *cmd); +extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); extern void scsi_free_queue(struct request_queue *q); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 38a41415004b..0a3a528212c2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -86,6 +86,19 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +static int sd_revalidate_disk(struct gendisk *); +static int sd_probe(struct device *); +static int sd_remove(struct device *); +static void sd_shutdown(struct device *); +static int sd_suspend(struct device *, pm_message_t state); +static int sd_resume(struct device *); +static void sd_rescan(struct device *); +static int sd_done(struct scsi_cmnd *); +static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); +static void scsi_disk_release(struct class_device *cdev); +static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); +static void sd_print_result(struct scsi_disk *, int); + static DEFINE_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); @@ -240,6 +253,7 @@ static struct scsi_driver sd_template = { .shutdown = sd_shutdown, }, .rescan = sd_rescan, + .done = sd_done, }; /* @@ -509,12 +523,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->timeout_per_command = timeout; /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = sd_rw_intr; - - /* * This indicates that the command is ready from our end to be * queued. */ @@ -908,13 +916,13 @@ static struct block_device_operations sd_fops = { }; /** - * sd_rw_intr - bottom half handler: called when the lower level + * sd_done - bottom half handler: called when the lower level * driver has completed (successfully or otherwise) a scsi command. * @SCpnt: mid-level's per command structure. * * Note: potentially run from within an ISR. Must not block. **/ -static void sd_rw_intr(struct scsi_cmnd * SCpnt) +static int sd_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; unsigned int xfer_size = SCpnt->request_bufflen; @@ -935,7 +943,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); if (sense_valid) { SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, - "sd_rw_intr: sb[respc,sk,asc," + "sd_done: sb[respc,sk,asc," "ascq]=%x,%x,%x,%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, @@ -1007,7 +1015,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) break; } out: - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } static int media_not_present(struct scsi_disk *sdkp, diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index a0c4e13d4dab..c61999031141 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -78,6 +78,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); static int sr_probe(struct device *); static int sr_remove(struct device *); +static int sr_done(struct scsi_cmnd *); static struct scsi_driver sr_template = { .owner = THIS_MODULE, @@ -86,6 +87,7 @@ static struct scsi_driver sr_template = { .probe = sr_probe, .remove = sr_remove, }, + .done = sr_done, }; static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; @@ -208,12 +210,12 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot) } /* - * rw_intr is the interrupt routine for the device driver. + * sr_done is the interrupt routine for the device driver. * - * It will be notified on the end of a SCSI read / write, and will take on + * It will be notified on the end of a SCSI read / write, and will take one * of several actions based on success or failure. */ -static void rw_intr(struct scsi_cmnd * SCpnt) +static int sr_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; int this_count = SCpnt->request_bufflen; @@ -286,12 +288,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt) } } - /* - * This calls the generic completion function, now that we know - * how many actual sectors finished, and how many sectors we need - * to say have failed. - */ - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } static int sr_prep_fn(struct request_queue *q, struct request *rq) @@ -428,12 +425,6 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCpnt->timeout_per_command = timeout; /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = rw_intr; - - /* * This indicates that the command is ready from our end to be * queued. */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 4fddef727467..65ab5145a09b 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -33,7 +33,6 @@ struct scsi_cmnd { struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head eh_entry; /* entry for the host eh_cmd_q */ int eh_eflags; /* Used by error handlr */ - void (*done) (struct scsi_cmnd *); /* Mid-level done function */ /* * A SCSI Command is assigned a nonzero serial_number before passed @@ -121,7 +120,6 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); -extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 56a304709fde..1f5ca7f62116 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -15,6 +15,7 @@ struct scsi_driver { struct device_driver gendrv; void (*rescan)(struct device *); + int (*done)(struct scsi_cmnd *); }; #define to_scsi_driver(drv) \ container_of((drv), struct scsi_driver, gendrv) diff --git a/include/scsi/sd.h b/include/scsi/sd.h index aa1e71613010..f7513313ef0d 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h @@ -47,19 +47,6 @@ struct scsi_disk { }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) -static int sd_revalidate_disk(struct gendisk *disk); -static void sd_rw_intr(struct scsi_cmnd * SCpnt); -static int sd_probe(struct device *); -static int sd_remove(struct device *); -static void sd_shutdown(struct device *dev); -static int sd_suspend(struct device *dev, pm_message_t state); -static int sd_resume(struct device *dev); -static void sd_rescan(struct device *); -static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); -static void scsi_disk_release(struct class_device *cdev); -static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); -static void sd_print_result(struct scsi_disk *, int); - #define sd_printk(prefix, sdsk, fmt, a...) \ (sdsk)->disk ? \ sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ |