Synchronizing caches may fail. The reason for these failures need to be translated to the generic layer so that it nows whether to ignore a failure, retry later or give up, aborting sleep. Signed-off-by: Oliver Neukum <oneukum@xxxxxxx> --- drivers/scsi/scsi_error.c | 33 +++++++++++++++++++++++++++++++++ drivers/scsi/sd.c | 3 +-- include/scsi/scsi_eh.h | 1 + 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4a6381c..13f7060 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2217,3 +2217,36 @@ void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) } } EXPORT_SYMBOL(scsi_build_sense_buffer); + +/** + * scsi_translate_errors_to_power_management - errors in a form driver core understands + * @res: Result of scsi command + * + * Return value: + * error code driver core understands + **/ +int scsi_translate_errors_to_power_management(int res) +{ + int rv = -EIO; + + switch (host_byte(res)) { + /* ignore errors due to racing a disconnection */ + case DID_BAD_TARGET: + case DID_NO_CONNECT: + return 0; + /* signal the upper layer it might try again */ + case DID_BUS_BUSY: + case DID_IMM_RETRY: + case DID_REQUEUE: + case DID_SOFT_ERROR: + case DID_TIME_OUT: + case DID_ABORT: + case DID_RESET: + case DID_TRANSPORT_DISRUPTED: + return -EBUSY; + case DID_OK: + return 0; + } + return rv; +} +EXPORT_SYMBOL(scsi_translate_errors_to_power_management); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c39a97e..8597294 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1288,10 +1288,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) */ if ((scsi_sense_valid(&sshdr) && sshdr.asc == 0x3a)) return 0; + return scsi_translate_errors_to_power_management(res); } - if (res) - return -EIO; return 0; } diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 06a8790..bdf6d6c 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -59,6 +59,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, u64 * info_out); extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); +extern int scsi_translate_errors_to_power_management(int res); /* * Reset request from external source -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html