From 79ee8304429b497263734e59747df12117de2ea2 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Aug 2007 14:50:42 -0700 Subject: [SCSI] scsi_error.c should #include "scsi_transport_api.h" Every file should #include the headers containing the prototypes for its global functions (in this case for scsi_schedule_eh()). Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 8a525abda30f..c8e351fb816c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -37,6 +37,7 @@ #include "scsi_priv.h" #include "scsi_logging.h" +#include "scsi_transport_api.h" #define SENSE_TIMEOUT (10*HZ) -- cgit v1.2.3 From 31765d7d3da9bb575f80faecae0b931afa3532c6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 17 Aug 2007 11:02:10 -0600 Subject: [SCSI] Improve error message when offlining a device The current code prints: scsi 13:0:4:0: scsi: Device offlined - not ready after error recovery which is repetitively redundant. This patch changes that message to: scsi 6:0:6:0: Device offlined - not ready after error recovery Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c8e351fb816c..c05d020bf926 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1137,9 +1137,8 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, struct scsi_cmnd *scmd, *next; list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - sdev_printk(KERN_INFO, scmd->device, - "scsi: Device offlined - not" - " ready after error recovery\n"); + sdev_printk(KERN_INFO, scmd->device, "Device offlined - " + "not ready after error recovery\n"); scsi_device_set_state(scmd->device, SDEV_OFFLINE); if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) { /* -- cgit v1.2.3 From 12a441622b753684cc73d1c6f225e9ac53e0bf77 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 18 Sep 2007 19:54:43 -0600 Subject: [SCSI] Remove ->pid field from scsi_cmnd The pid field is a duplicate of the serial_number field and has been scheduled for removal for a long time. A few drivers were still using it, so just change them to use serial_number instead. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c05d020bf926..44e6721ddea6 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1681,12 +1681,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) init_timer(&scmd->eh_timeout); - /* - * Sometimes the command can get back into the timer chain, - * so use the pid as an identifier. - */ - scmd->pid = 0; - spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); -- cgit v1.2.3 From 6f5391c283d7fdcf24bf40786ea79061919d1e1d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 25 Sep 2007 12:42:04 -0400 Subject: [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 Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi/scsi_error.c') 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; -- cgit v1.2.3 From 55db6c1b8ed52bfc876e87971de8c67c42f36909 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 8 Oct 2007 16:35:19 +0200 Subject: [SCSI] scsi_error: code cleanup before refactoring of scsi_send_eh_cmnd() - regrouped variables for easier reviewing of next patch - Support of cmnd==NULL in call to scsi_send_eh_cmnd() - In the @sense_bytes case set transfer size to the minimum size of sense_buffer and passed @sense_bytes. cmnd[4] is set accordingly. - REQUEST_SENSE is set into cmnd[0] so if @sense_bytes is not Zero passed @cmnd should be NULL. - Also save/restore resid of failed command. - Adjust caller Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 71 ++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 32 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f49feb9351d0..4d535019e04b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -592,36 +592,39 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) /** * scsi_send_eh_cmnd - submit a scsi command as part of error recory * @scmd: SCSI command structure to hijack - * @cmnd: CDB to send + * @cmnd: CDB to send. Can be NULL if no new cmnd is needed * @cmnd_size: size in bytes of @cmnd * @timeout: timeout for this request - * @copy_sense: request sense data if set to 1 + * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to send a scsi command down to a target device - * as part of the error recovery process. If @copy_sense is 0 the command - * sent must be one that does not transfer any data. If @copy_sense is 1 - * the command must be REQUEST_SENSE and this functions copies out the - * sense buffer it got into @scmd->sense_buffer. + * as part of the error recovery process. If @sense_bytes is 0 the command + * sent must be one that does not transfer any data. If @sense_bytes != 0 + * @cmnd is ignored and this functions sets up a REQUEST_SENSE command + * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer. * * Return value: * SUCCESS or FAILED or NEEDS_RETRY **/ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, - int cmnd_size, int timeout, int copy_sense) + int cmnd_size, int timeout, unsigned sense_bytes) { struct scsi_device *sdev = scmd->device; struct Scsi_Host *shost = sdev->host; - int old_result = scmd->result; DECLARE_COMPLETION_ONSTACK(done); unsigned long timeleft; unsigned long flags; - struct scatterlist sgl; + + unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; enum dma_data_direction old_data_direction; - unsigned short old_use_sg; - unsigned char old_cmd_len; unsigned old_bufflen; void *old_buffer; + unsigned short old_use_sg; + int old_resid; + int old_result; + + struct scatterlist sgl; int rtn; /* @@ -631,35 +634,41 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * we will need to restore these values prior to running the actual * command. */ - old_buffer = scmd->request_buffer; - old_bufflen = scmd->request_bufflen; + old_cmd_len = scmd->cmd_len; memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); old_data_direction = scmd->sc_data_direction; - old_cmd_len = scmd->cmd_len; + old_bufflen = scmd->request_bufflen; + old_buffer = scmd->request_buffer; old_use_sg = scmd->use_sg; + old_resid = scmd->resid; + old_result = scmd->result; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); - memcpy(scmd->cmnd, cmnd, cmnd_size); - - if (copy_sense) { - sg_init_one(&sgl, scmd->sense_buffer, - sizeof(scmd->sense_buffer)); - - scmd->sc_data_direction = DMA_FROM_DEVICE; - scmd->request_bufflen = sgl.length; + if (sense_bytes) { + scmd->request_bufflen = min_t(unsigned, + sizeof(scmd->sense_buffer), sense_bytes); + sg_init_one(&sgl, scmd->sense_buffer, scmd->request_bufflen); scmd->request_buffer = &sgl; + scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->use_sg = 1; + memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + scmd->cmnd[0] = REQUEST_SENSE; + scmd->cmnd[4] = scmd->request_bufflen; + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->request_buffer = NULL; scmd->request_bufflen = 0; scmd->sc_data_direction = DMA_NONE; scmd->use_sg = 0; + if (cmnd) { + memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + memcpy(scmd->cmnd, cmnd, cmnd_size); + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); + } } scmd->underflow = 0; - scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); - if (sdev->scsi_level <= SCSI_2) + if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN) scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | (sdev->lun << 5 & 0xe0); @@ -716,12 +725,13 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, /* * Restore original data */ - scmd->request_buffer = old_buffer; - scmd->request_bufflen = old_bufflen; + scmd->cmd_len = old_cmd_len; memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd)); scmd->sc_data_direction = old_data_direction; - scmd->cmd_len = old_cmd_len; + scmd->request_bufflen = old_bufflen; + scmd->request_buffer = old_buffer; scmd->use_sg = old_use_sg; + scmd->resid = old_resid; scmd->result = old_result; return rtn; } @@ -737,10 +747,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, **/ static int scsi_request_sense(struct scsi_cmnd *scmd) { - static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 252, 0}; - - return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1); + return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0); } /** -- cgit v1.2.3 From e1c234685c50807e10a3e7873e6e006976a4d8e8 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 8 Oct 2007 16:36:45 +0200 Subject: [SCSI] scsi_error: Refactoring scsi_error to facilitate in synchronous REQUEST_SENSE - Drivers/transports that want to send a synchronous REQUEST_SENSE command as part of their .queuecommand sequence, have 2 new API's that facilitate in doing so and abstract them from scsi-ml internals. void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *sesci, unsigned char *cmnd, int cmnd_size, int sense_bytes) Will hijack a command and prepare it for request sense if needed. And will save any later needed info into a scsi_eh_save structure. void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *sesci); Will undo any changes done to a command by above function. Making it ready for completion. - Re-factor scsi_send_eh_cmnd() to use above APIs Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 114 +++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 46 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4d535019e04b..d29f8464b74f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -590,42 +590,23 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) } /** - * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * scsi_eh_prep_cmnd - Save a scsi command info as part of error recory * @scmd: SCSI command structure to hijack + * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed * @cmnd_size: size in bytes of @cmnd - * @timeout: timeout for this request * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * - * This function is used to send a scsi command down to a target device + * This function is used to save a scsi command information before re-execution * as part of the error recovery process. If @sense_bytes is 0 the command * sent must be one that does not transfer any data. If @sense_bytes != 0 * @cmnd is ignored and this functions sets up a REQUEST_SENSE command * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer. - * - * Return value: - * SUCCESS or FAILED or NEEDS_RETRY **/ -static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, - int cmnd_size, int timeout, unsigned sense_bytes) +void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, + unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) { struct scsi_device *sdev = scmd->device; - struct Scsi_Host *shost = sdev->host; - DECLARE_COMPLETION_ONSTACK(done); - unsigned long timeleft; - unsigned long flags; - - unsigned char old_cmd_len; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - enum dma_data_direction old_data_direction; - unsigned old_bufflen; - void *old_buffer; - unsigned short old_use_sg; - int old_resid; - int old_result; - - struct scatterlist sgl; - int rtn; /* * We need saved copies of a number of fields - this is because @@ -634,20 +615,21 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * we will need to restore these values prior to running the actual * command. */ - old_cmd_len = scmd->cmd_len; - memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); - old_data_direction = scmd->sc_data_direction; - old_bufflen = scmd->request_bufflen; - old_buffer = scmd->request_buffer; - old_use_sg = scmd->use_sg; - old_resid = scmd->resid; - old_result = scmd->result; + ses->cmd_len = scmd->cmd_len; + memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->data_direction = scmd->sc_data_direction; + ses->bufflen = scmd->request_bufflen; + ses->buffer = scmd->request_buffer; + ses->use_sg = scmd->use_sg; + ses->resid = scmd->resid; + ses->result = scmd->result; if (sense_bytes) { scmd->request_bufflen = min_t(unsigned, sizeof(scmd->sense_buffer), sense_bytes); - sg_init_one(&sgl, scmd->sense_buffer, scmd->request_bufflen); - scmd->request_buffer = &sgl; + sg_init_one(&ses->sense_sgl, scmd->sense_buffer, + scmd->request_bufflen); + scmd->request_buffer = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->use_sg = 1; memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); @@ -677,7 +659,58 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * untransferred sense data should be interpreted as being zero. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); +} +EXPORT_SYMBOL(scsi_eh_prep_cmnd); + +/** + * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recory + * @scmd: SCSI command structure to restore + * @ses: saved information from a coresponding call to scsi_prep_eh_cmnd + * + * Undo any damage done by above scsi_prep_eh_cmnd(). + **/ +void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) +{ + /* + * Restore original data + */ + scmd->cmd_len = ses->cmd_len; + memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->sc_data_direction = ses->data_direction; + scmd->request_bufflen = ses->bufflen; + scmd->request_buffer = ses->buffer; + scmd->use_sg = ses->use_sg; + scmd->resid = ses->resid; + scmd->result = ses->result; +} +EXPORT_SYMBOL(scsi_eh_restore_cmnd); +/** + * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * @scmd: SCSI command structure to hijack + * @cmnd: CDB to send + * @cmnd_size: size in bytes of @cmnd + * @timeout: timeout for this request + * @sense_bytes: size of sense data to copy or 0 + * + * This function is used to send a scsi command down to a target device + * as part of the error recovery process. See also scsi_eh_prep_cmnd() above. + * + * Return value: + * SUCCESS or FAILED or NEEDS_RETRY + **/ +static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, + int cmnd_size, int timeout, unsigned sense_bytes) +{ + struct scsi_device *sdev = scmd->device; + struct Scsi_Host *shost = sdev->host; + DECLARE_COMPLETION_ONSTACK(done); + unsigned long timeleft; + unsigned long flags; + struct scsi_eh_save ses; + int rtn; + + scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); shost->eh_action = &done; spin_lock_irqsave(shost->host_lock, flags); @@ -721,18 +754,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, rtn = FAILED; } - - /* - * Restore original data - */ - scmd->cmd_len = old_cmd_len; - memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd)); - scmd->sc_data_direction = old_data_direction; - scmd->request_bufflen = old_bufflen; - scmd->request_buffer = old_buffer; - scmd->use_sg = old_use_sg; - scmd->resid = old_resid; - scmd->result = old_result; + scsi_eh_restore_cmnd(scmd, &ses); return rtn; } -- cgit v1.2.3