11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * scsi_error.c Copyright (C) 1997 Eric Youngdale 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * SCSI error/timeout handling 51da177e4SLinus Torvalds * Initial versions: Eric Youngdale. Based upon conversations with 61da177e4SLinus Torvalds * Leonard Zubkoff and David Miller at Linux Expo, 71da177e4SLinus Torvalds * ideas originating from all over the place. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Restructured scsi_unjam_host and associated functions. 101da177e4SLinus Torvalds * September 04, 2002 Mike Anderson (andmike@us.ibm.com) 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Forward port of Russell King's (rmk@arm.linux.org.uk) changes and 131da177e4SLinus Torvalds * minor cleanups. 141da177e4SLinus Torvalds * September 30, 2002 Mike Anderson (andmike@us.ibm.com) 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #include <linux/module.h> 181da177e4SLinus Torvalds #include <linux/sched.h> 195a0e3ad6STejun Heo #include <linux/gfp.h> 201da177e4SLinus Torvalds #include <linux/timer.h> 211da177e4SLinus Torvalds #include <linux/string.h> 221da177e4SLinus Torvalds #include <linux/kernel.h> 2383144186SRafael J. Wysocki #include <linux/freezer.h> 24c5478defSChristoph Hellwig #include <linux/kthread.h> 251da177e4SLinus Torvalds #include <linux/interrupt.h> 261da177e4SLinus Torvalds #include <linux/blkdev.h> 271da177e4SLinus Torvalds #include <linux/delay.h> 28fc73648aSHannes Reinecke #include <linux/jiffies.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <scsi/scsi.h> 31beb40487SChristoph Hellwig #include <scsi/scsi_cmnd.h> 321da177e4SLinus Torvalds #include <scsi/scsi_dbg.h> 331da177e4SLinus Torvalds #include <scsi/scsi_device.h> 3418a4d0a2SMartin K. Petersen #include <scsi/scsi_driver.h> 351da177e4SLinus Torvalds #include <scsi/scsi_eh.h> 367708c165SSagi Grimberg #include <scsi/scsi_common.h> 37c829c394SJames Smart #include <scsi/scsi_transport.h> 381da177e4SLinus Torvalds #include <scsi/scsi_host.h> 391da177e4SLinus Torvalds #include <scsi/scsi_ioctl.h> 40ee14c674SChristoph Hellwig #include <scsi/scsi_dh.h> 41176aa9d6SChristoph Hellwig #include <scsi/sg.h> 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #include "scsi_priv.h" 441da177e4SLinus Torvalds #include "scsi_logging.h" 4579ee8304SAdrian Bunk #include "scsi_transport_api.h" 461da177e4SLinus Torvalds 47bf816235SKei Tokunaga #include <trace/events/scsi.h> 48bf816235SKei Tokunaga 492908769cSDamien Le Moal #include <asm/unaligned.h> 502908769cSDamien Le Moal 5114216561SJames Bottomley static void scsi_eh_done(struct scsi_cmnd *scmd); 5214216561SJames Bottomley 531da177e4SLinus Torvalds /* 541da177e4SLinus Torvalds * These should *probably* be handled by the host itself. 551da177e4SLinus Torvalds * Since it is allowed to sleep, it probably should. 561da177e4SLinus Torvalds */ 571da177e4SLinus Torvalds #define BUS_RESET_SETTLE_TIME (10) 581da177e4SLinus Torvalds #define HOST_RESET_SETTLE_TIME (10) 591da177e4SLinus Torvalds 603eef6257SDavid Jeffery static int scsi_eh_try_stu(struct scsi_cmnd *scmd); 61e494f6a7SHannes Reinecke static int scsi_try_to_abort_cmd(struct scsi_host_template *, 62e494f6a7SHannes Reinecke struct scsi_cmnd *); 633eef6257SDavid Jeffery 641da177e4SLinus Torvalds /* called with shost->host_lock held */ 651da177e4SLinus Torvalds void scsi_eh_wakeup(struct Scsi_Host *shost) 661da177e4SLinus Torvalds { 6774665016SChristoph Hellwig if (atomic_read(&shost->host_busy) == shost->host_failed) { 68bf816235SKei Tokunaga trace_scsi_eh_wakeup(shost); 693ed7a470SJames Bottomley wake_up_process(shost->ehandler); 7091921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost, 7191921e01SHannes Reinecke "Waking error handler thread\n")); 721da177e4SLinus Torvalds } 731da177e4SLinus Torvalds } 74f8bbfc24STejun Heo 75f8bbfc24STejun Heo /** 76f8bbfc24STejun Heo * scsi_schedule_eh - schedule EH for SCSI host 77f8bbfc24STejun Heo * @shost: SCSI host to invoke error handling on. 78f8bbfc24STejun Heo * 79f8bbfc24STejun Heo * Schedule SCSI EH without scmd. 80dc8875e1SRandy Dunlap */ 81f8bbfc24STejun Heo void scsi_schedule_eh(struct Scsi_Host *shost) 82f8bbfc24STejun Heo { 83f8bbfc24STejun Heo unsigned long flags; 84f8bbfc24STejun Heo 85f8bbfc24STejun Heo spin_lock_irqsave(shost->host_lock, flags); 86f8bbfc24STejun Heo 87f8bbfc24STejun Heo if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || 88f8bbfc24STejun Heo scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { 89f8bbfc24STejun Heo shost->host_eh_scheduled++; 90f8bbfc24STejun Heo scsi_eh_wakeup(shost); 91f8bbfc24STejun Heo } 92f8bbfc24STejun Heo 93f8bbfc24STejun Heo spin_unlock_irqrestore(shost->host_lock, flags); 94f8bbfc24STejun Heo } 95f8bbfc24STejun Heo EXPORT_SYMBOL_GPL(scsi_schedule_eh); 961da177e4SLinus Torvalds 97b4562022SHannes Reinecke static int scsi_host_eh_past_deadline(struct Scsi_Host *shost) 98b4562022SHannes Reinecke { 99bb3b621aSRen Mingxin if (!shost->last_reset || shost->eh_deadline == -1) 100b4562022SHannes Reinecke return 0; 101b4562022SHannes Reinecke 10276ad3e59SHannes Reinecke /* 10376ad3e59SHannes Reinecke * 32bit accesses are guaranteed to be atomic 10476ad3e59SHannes Reinecke * (on all supported architectures), so instead 10576ad3e59SHannes Reinecke * of using a spinlock we can as well double check 106bb3b621aSRen Mingxin * if eh_deadline has been set to 'off' during the 10776ad3e59SHannes Reinecke * time_before call. 10876ad3e59SHannes Reinecke */ 10976ad3e59SHannes Reinecke if (time_before(jiffies, shost->last_reset + shost->eh_deadline) && 110bb3b621aSRen Mingxin shost->eh_deadline > -1) 111b4562022SHannes Reinecke return 0; 112b4562022SHannes Reinecke 113b4562022SHannes Reinecke return 1; 114b4562022SHannes Reinecke } 115b4562022SHannes Reinecke 1161da177e4SLinus Torvalds /** 117e494f6a7SHannes Reinecke * scmd_eh_abort_handler - Handle command aborts 118e494f6a7SHannes Reinecke * @work: command to be aborted. 119e494f6a7SHannes Reinecke */ 120e494f6a7SHannes Reinecke void 121e494f6a7SHannes Reinecke scmd_eh_abort_handler(struct work_struct *work) 122e494f6a7SHannes Reinecke { 123e494f6a7SHannes Reinecke struct scsi_cmnd *scmd = 124e494f6a7SHannes Reinecke container_of(work, struct scsi_cmnd, abort_work.work); 125e494f6a7SHannes Reinecke struct scsi_device *sdev = scmd->device; 126e494f6a7SHannes Reinecke int rtn; 127e494f6a7SHannes Reinecke 128e494f6a7SHannes Reinecke if (scsi_host_eh_past_deadline(sdev->host)) { 129e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 130e494f6a7SHannes Reinecke scmd_printk(KERN_INFO, scmd, 131470613b4SHannes Reinecke "eh timeout, not aborting\n")); 132e494f6a7SHannes Reinecke } else { 133e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 134e494f6a7SHannes Reinecke scmd_printk(KERN_INFO, scmd, 135470613b4SHannes Reinecke "aborting command\n")); 136e494f6a7SHannes Reinecke rtn = scsi_try_to_abort_cmd(sdev->host->hostt, scmd); 137e494f6a7SHannes Reinecke if (rtn == SUCCESS) { 1388922a908SUlrich Obergfell set_host_byte(scmd, DID_TIME_OUT); 139bb3b621aSRen Mingxin if (scsi_host_eh_past_deadline(sdev->host)) { 140bb3b621aSRen Mingxin SCSI_LOG_ERROR_RECOVERY(3, 141bb3b621aSRen Mingxin scmd_printk(KERN_INFO, scmd, 142470613b4SHannes Reinecke "eh timeout, not retrying " 143470613b4SHannes Reinecke "aborted command\n")); 144bb3b621aSRen Mingxin } else if (!scsi_noretry_cmd(scmd) && 145e494f6a7SHannes Reinecke (++scmd->retries <= scmd->allowed)) { 146e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 147e494f6a7SHannes Reinecke scmd_printk(KERN_WARNING, scmd, 148470613b4SHannes Reinecke "retry aborted command\n")); 149e494f6a7SHannes Reinecke scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); 150bb3b621aSRen Mingxin return; 151e494f6a7SHannes Reinecke } else { 152e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 153e494f6a7SHannes Reinecke scmd_printk(KERN_WARNING, scmd, 154470613b4SHannes Reinecke "finish aborted command\n")); 155e494f6a7SHannes Reinecke scsi_finish_command(scmd); 156e494f6a7SHannes Reinecke return; 157e494f6a7SHannes Reinecke } 158bb3b621aSRen Mingxin } else { 159e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 160e494f6a7SHannes Reinecke scmd_printk(KERN_INFO, scmd, 161470613b4SHannes Reinecke "cmd abort %s\n", 162883a030fSHannes Reinecke (rtn == FAST_IO_FAIL) ? 163883a030fSHannes Reinecke "not send" : "failed")); 164e494f6a7SHannes Reinecke } 165bb3b621aSRen Mingxin } 166e494f6a7SHannes Reinecke 167a0658632SHannes Reinecke scsi_eh_scmd_add(scmd); 168e494f6a7SHannes Reinecke } 169e494f6a7SHannes Reinecke 170e494f6a7SHannes Reinecke /** 171e494f6a7SHannes Reinecke * scsi_abort_command - schedule a command abort 172e494f6a7SHannes Reinecke * @scmd: scmd to abort. 173e494f6a7SHannes Reinecke * 174e494f6a7SHannes Reinecke * We only need to abort commands after a command timeout 175e494f6a7SHannes Reinecke */ 176e494f6a7SHannes Reinecke static int 177e494f6a7SHannes Reinecke scsi_abort_command(struct scsi_cmnd *scmd) 178e494f6a7SHannes Reinecke { 179e494f6a7SHannes Reinecke struct scsi_device *sdev = scmd->device; 180e494f6a7SHannes Reinecke struct Scsi_Host *shost = sdev->host; 181e494f6a7SHannes Reinecke unsigned long flags; 182e494f6a7SHannes Reinecke 183e494f6a7SHannes Reinecke if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) { 184e494f6a7SHannes Reinecke /* 185e494f6a7SHannes Reinecke * Retry after abort failed, escalate to next level. 186e494f6a7SHannes Reinecke */ 187e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 188e494f6a7SHannes Reinecke scmd_printk(KERN_INFO, scmd, 189470613b4SHannes Reinecke "previous abort failed\n")); 190fcc95a76SBart Van Assche BUG_ON(delayed_work_pending(&scmd->abort_work)); 191e494f6a7SHannes Reinecke return FAILED; 192e494f6a7SHannes Reinecke } 193e494f6a7SHannes Reinecke 194e494f6a7SHannes Reinecke spin_lock_irqsave(shost->host_lock, flags); 195bb3b621aSRen Mingxin if (shost->eh_deadline != -1 && !shost->last_reset) 196e494f6a7SHannes Reinecke shost->last_reset = jiffies; 197e494f6a7SHannes Reinecke spin_unlock_irqrestore(shost->host_lock, flags); 198e494f6a7SHannes Reinecke 199e494f6a7SHannes Reinecke scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED; 200e494f6a7SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 201470613b4SHannes Reinecke scmd_printk(KERN_INFO, scmd, "abort scheduled\n")); 202e494f6a7SHannes Reinecke queue_delayed_work(shost->tmf_work_q, &scmd->abort_work, HZ / 100); 203e494f6a7SHannes Reinecke return SUCCESS; 204e494f6a7SHannes Reinecke } 205e494f6a7SHannes Reinecke 206e494f6a7SHannes Reinecke /** 2077a38dc0bSHannes Reinecke * scsi_eh_reset - call into ->eh_action to reset internal counters 2087a38dc0bSHannes Reinecke * @scmd: scmd to run eh on. 2097a38dc0bSHannes Reinecke * 2107a38dc0bSHannes Reinecke * The scsi driver might be carrying internal state about the 2117a38dc0bSHannes Reinecke * devices, so we need to call into the driver to reset the 2127a38dc0bSHannes Reinecke * internal state once the error handler is started. 2137a38dc0bSHannes Reinecke */ 2147a38dc0bSHannes Reinecke static void scsi_eh_reset(struct scsi_cmnd *scmd) 2157a38dc0bSHannes Reinecke { 2167a38dc0bSHannes Reinecke if (!blk_rq_is_passthrough(scmd->request)) { 2177a38dc0bSHannes Reinecke struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); 2187a38dc0bSHannes Reinecke if (sdrv->eh_reset) 2197a38dc0bSHannes Reinecke sdrv->eh_reset(scmd); 2207a38dc0bSHannes Reinecke } 2217a38dc0bSHannes Reinecke } 2227a38dc0bSHannes Reinecke 2237a38dc0bSHannes Reinecke /** 2241da177e4SLinus Torvalds * scsi_eh_scmd_add - add scsi cmd to error handling. 2251da177e4SLinus Torvalds * @scmd: scmd to run eh on. 226dc8875e1SRandy Dunlap */ 227a0658632SHannes Reinecke void scsi_eh_scmd_add(struct scsi_cmnd *scmd) 2281da177e4SLinus Torvalds { 2291da177e4SLinus Torvalds struct Scsi_Host *shost = scmd->device->host; 2301da177e4SLinus Torvalds unsigned long flags; 2312171b6d0SHannes Reinecke int ret; 2321da177e4SLinus Torvalds 2332171b6d0SHannes Reinecke WARN_ON_ONCE(!shost->ehandler); 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 2362171b6d0SHannes Reinecke if (scsi_host_set_state(shost, SHOST_RECOVERY)) { 2372171b6d0SHannes Reinecke ret = scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY); 2382171b6d0SHannes Reinecke WARN_ON_ONCE(ret); 2392171b6d0SHannes Reinecke } 240bb3b621aSRen Mingxin if (shost->eh_deadline != -1 && !shost->last_reset) 241b4562022SHannes Reinecke shost->last_reset = jiffies; 242b4562022SHannes Reinecke 2437a38dc0bSHannes Reinecke scsi_eh_reset(scmd); 2441da177e4SLinus Torvalds list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); 2451da177e4SLinus Torvalds shost->host_failed++; 2461da177e4SLinus Torvalds scsi_eh_wakeup(shost); 2471da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /** 2511da177e4SLinus Torvalds * scsi_times_out - Timeout function for normal scsi commands. 252242f9dcbSJens Axboe * @req: request that is timing out. 2531da177e4SLinus Torvalds * 2541da177e4SLinus Torvalds * Notes: 2551da177e4SLinus Torvalds * We do not need to lock this. There is the potential for a race 2561da177e4SLinus Torvalds * only in that the normal completion handling might run, but if the 2571da177e4SLinus Torvalds * normal completion function determines that the timer has already 2581da177e4SLinus Torvalds * fired, then it mustn't do anything. 259dc8875e1SRandy Dunlap */ 260242f9dcbSJens Axboe enum blk_eh_timer_return scsi_times_out(struct request *req) 2611da177e4SLinus Torvalds { 262bed2213dSBart Van Assche struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); 263242f9dcbSJens Axboe enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED; 2640bf8c869SJesper Juhl struct Scsi_Host *host = scmd->device->host; 2656c5f8ce1SJames Bottomley 266bf816235SKei Tokunaga trace_scsi_dispatch_cmd_timeout(scmd); 2671da177e4SLinus Torvalds scsi_log_completion(scmd, TIMEOUT_ERROR); 2681da177e4SLinus Torvalds 269bb3b621aSRen Mingxin if (host->eh_deadline != -1 && !host->last_reset) 270b4562022SHannes Reinecke host->last_reset = jiffies; 271b4562022SHannes Reinecke 272b6a05c82SChristoph Hellwig if (host->hostt->eh_timed_out) 2730bf8c869SJesper Juhl rtn = host->hostt->eh_timed_out(scmd); 2746c5f8ce1SJames Bottomley 275a33c070bSHannes Reinecke if (rtn == BLK_EH_NOT_HANDLED) { 276a0658632SHannes Reinecke if (scsi_abort_command(scmd) != SUCCESS) { 2778922a908SUlrich Obergfell set_host_byte(scmd, DID_TIME_OUT); 278a0658632SHannes Reinecke scsi_eh_scmd_add(scmd); 2792171b6d0SHannes Reinecke } 280a33c070bSHannes Reinecke } 281242f9dcbSJens Axboe 282fa990781SChristoph Hellwig return rtn; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds /** 2861da177e4SLinus Torvalds * scsi_block_when_processing_errors - Prevent cmds from being queued. 2871da177e4SLinus Torvalds * @sdev: Device on which we are performing recovery. 2881da177e4SLinus Torvalds * 2891da177e4SLinus Torvalds * Description: 2901da177e4SLinus Torvalds * We block until the host is out of error recovery, and then check to 2911da177e4SLinus Torvalds * see whether the host or the device is offline. 2921da177e4SLinus Torvalds * 2931da177e4SLinus Torvalds * Return value: 2941da177e4SLinus Torvalds * 0 when dev was taken offline by error recovery. 1 OK to proceed. 295dc8875e1SRandy Dunlap */ 2961da177e4SLinus Torvalds int scsi_block_when_processing_errors(struct scsi_device *sdev) 2971da177e4SLinus Torvalds { 2981da177e4SLinus Torvalds int online; 2991da177e4SLinus Torvalds 300939647eeSJames Bottomley wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host)); 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds online = scsi_device_online(sdev); 3031da177e4SLinus Torvalds 30491921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_INFO, sdev, 30591921e01SHannes Reinecke "%s: rtn: %d\n", __func__, online)); 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds return online; 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_block_when_processing_errors); 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds #ifdef CONFIG_SCSI_LOGGING 3121da177e4SLinus Torvalds /** 3131da177e4SLinus Torvalds * scsi_eh_prt_fail_stats - Log info on failures. 3141da177e4SLinus Torvalds * @shost: scsi host being recovered. 3151da177e4SLinus Torvalds * @work_q: Queue of scsi cmds to process. 316dc8875e1SRandy Dunlap */ 3171da177e4SLinus Torvalds static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, 3181da177e4SLinus Torvalds struct list_head *work_q) 3191da177e4SLinus Torvalds { 3201da177e4SLinus Torvalds struct scsi_cmnd *scmd; 3211da177e4SLinus Torvalds struct scsi_device *sdev; 3221da177e4SLinus Torvalds int total_failures = 0; 3231da177e4SLinus Torvalds int cmd_failed = 0; 3241da177e4SLinus Torvalds int cmd_cancel = 0; 3251da177e4SLinus Torvalds int devices_failed = 0; 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds shost_for_each_device(sdev, shost) { 3281da177e4SLinus Torvalds list_for_each_entry(scmd, work_q, eh_entry) { 3291da177e4SLinus Torvalds if (scmd->device == sdev) { 3301da177e4SLinus Torvalds ++total_failures; 331a0658632SHannes Reinecke if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) 3321da177e4SLinus Torvalds ++cmd_cancel; 3331da177e4SLinus Torvalds else 3341da177e4SLinus Torvalds ++cmd_failed; 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds if (cmd_cancel || cmd_failed) { 3391da177e4SLinus Torvalds SCSI_LOG_ERROR_RECOVERY(3, 340a3a790dcSHannes Reinecke shost_printk(KERN_INFO, shost, 3419ccfc756SJames Bottomley "%s: cmds failed: %d, cancel: %d\n", 342cadbd4a5SHarvey Harrison __func__, cmd_failed, 3439ccfc756SJames Bottomley cmd_cancel)); 3441da177e4SLinus Torvalds cmd_cancel = 0; 3451da177e4SLinus Torvalds cmd_failed = 0; 3461da177e4SLinus Torvalds ++devices_failed; 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds 35091921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost, 35191921e01SHannes Reinecke "Total of %d commands on %d" 3521da177e4SLinus Torvalds " devices require eh work\n", 3531da177e4SLinus Torvalds total_failures, devices_failed)); 3541da177e4SLinus Torvalds } 3551da177e4SLinus Torvalds #endif 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds /** 358279afdfeSEwan D. Milne * scsi_report_lun_change - Set flag on all *other* devices on the same target 359279afdfeSEwan D. Milne * to indicate that a UNIT ATTENTION is expected. 360279afdfeSEwan D. Milne * @sdev: Device reporting the UNIT ATTENTION 361279afdfeSEwan D. Milne */ 362279afdfeSEwan D. Milne static void scsi_report_lun_change(struct scsi_device *sdev) 363279afdfeSEwan D. Milne { 364279afdfeSEwan D. Milne sdev->sdev_target->expecting_lun_change = 1; 365279afdfeSEwan D. Milne } 366279afdfeSEwan D. Milne 367279afdfeSEwan D. Milne /** 368279afdfeSEwan D. Milne * scsi_report_sense - Examine scsi sense information and log messages for 369279afdfeSEwan D. Milne * certain conditions, also issue uevents for some of them. 370279afdfeSEwan D. Milne * @sdev: Device reporting the sense code 371279afdfeSEwan D. Milne * @sshdr: sshdr to be examined 372279afdfeSEwan D. Milne */ 373279afdfeSEwan D. Milne static void scsi_report_sense(struct scsi_device *sdev, 374279afdfeSEwan D. Milne struct scsi_sense_hdr *sshdr) 375279afdfeSEwan D. Milne { 376279afdfeSEwan D. Milne enum scsi_device_event evt_type = SDEV_EVT_MAXBITS; /* i.e. none */ 377279afdfeSEwan D. Milne 378279afdfeSEwan D. Milne if (sshdr->sense_key == UNIT_ATTENTION) { 379279afdfeSEwan D. Milne if (sshdr->asc == 0x3f && sshdr->ascq == 0x03) { 380279afdfeSEwan D. Milne evt_type = SDEV_EVT_INQUIRY_CHANGE_REPORTED; 381279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 382279afdfeSEwan D. Milne "Inquiry data has changed"); 383279afdfeSEwan D. Milne } else if (sshdr->asc == 0x3f && sshdr->ascq == 0x0e) { 384279afdfeSEwan D. Milne evt_type = SDEV_EVT_LUN_CHANGE_REPORTED; 385279afdfeSEwan D. Milne scsi_report_lun_change(sdev); 386279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 387279afdfeSEwan D. Milne "Warning! Received an indication that the " 388279afdfeSEwan D. Milne "LUN assignments on this target have " 389279afdfeSEwan D. Milne "changed. The Linux SCSI layer does not " 390279afdfeSEwan D. Milne "automatically remap LUN assignments.\n"); 391279afdfeSEwan D. Milne } else if (sshdr->asc == 0x3f) 392279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 393279afdfeSEwan D. Milne "Warning! Received an indication that the " 394279afdfeSEwan D. Milne "operating parameters on this target have " 395279afdfeSEwan D. Milne "changed. The Linux SCSI layer does not " 396279afdfeSEwan D. Milne "automatically adjust these parameters.\n"); 397279afdfeSEwan D. Milne 398279afdfeSEwan D. Milne if (sshdr->asc == 0x38 && sshdr->ascq == 0x07) { 399279afdfeSEwan D. Milne evt_type = SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED; 400279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 401279afdfeSEwan D. Milne "Warning! Received an indication that the " 402279afdfeSEwan D. Milne "LUN reached a thin provisioning soft " 403279afdfeSEwan D. Milne "threshold.\n"); 404279afdfeSEwan D. Milne } 405279afdfeSEwan D. Milne 406cf3431bbSHannes Reinecke if (sshdr->asc == 0x29) { 407cf3431bbSHannes Reinecke evt_type = SDEV_EVT_POWER_ON_RESET_OCCURRED; 408cf3431bbSHannes Reinecke sdev_printk(KERN_WARNING, sdev, 409cf3431bbSHannes Reinecke "Power-on or device reset occurred\n"); 410cf3431bbSHannes Reinecke } 411cf3431bbSHannes Reinecke 412279afdfeSEwan D. Milne if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) { 413279afdfeSEwan D. Milne evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED; 414279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 415279afdfeSEwan D. Milne "Mode parameters changed"); 41614c3e677SHannes Reinecke } else if (sshdr->asc == 0x2a && sshdr->ascq == 0x06) { 41714c3e677SHannes Reinecke evt_type = SDEV_EVT_ALUA_STATE_CHANGE_REPORTED; 41814c3e677SHannes Reinecke sdev_printk(KERN_WARNING, sdev, 41914c3e677SHannes Reinecke "Asymmetric access state changed"); 420279afdfeSEwan D. Milne } else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) { 421279afdfeSEwan D. Milne evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED; 422279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 423279afdfeSEwan D. Milne "Capacity data has changed"); 424279afdfeSEwan D. Milne } else if (sshdr->asc == 0x2a) 425279afdfeSEwan D. Milne sdev_printk(KERN_WARNING, sdev, 426279afdfeSEwan D. Milne "Parameters changed"); 427279afdfeSEwan D. Milne } 428279afdfeSEwan D. Milne 429279afdfeSEwan D. Milne if (evt_type != SDEV_EVT_MAXBITS) { 430279afdfeSEwan D. Milne set_bit(evt_type, sdev->pending_events); 431279afdfeSEwan D. Milne schedule_work(&sdev->event_work); 432279afdfeSEwan D. Milne } 433279afdfeSEwan D. Milne } 434279afdfeSEwan D. Milne 435279afdfeSEwan D. Milne /** 4361da177e4SLinus Torvalds * scsi_check_sense - Examine scsi cmd sense 4371da177e4SLinus Torvalds * @scmd: Cmd to have sense checked. 4381da177e4SLinus Torvalds * 4391da177e4SLinus Torvalds * Return value: 44087f14e65SHannes Reinecke * SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE 4411da177e4SLinus Torvalds * 4421da177e4SLinus Torvalds * Notes: 4431da177e4SLinus Torvalds * When a deferred error is detected the current command has 4441da177e4SLinus Torvalds * not been executed and needs retrying. 445dc8875e1SRandy Dunlap */ 4463852e373SHannes Reinecke int scsi_check_sense(struct scsi_cmnd *scmd) 4471da177e4SLinus Torvalds { 448a6a8d9f8SChandra Seetharaman struct scsi_device *sdev = scmd->device; 4491da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds if (! scsi_command_normalize_sense(scmd, &sshdr)) 4521da177e4SLinus Torvalds return FAILED; /* no valid sense data */ 4531da177e4SLinus Torvalds 454279afdfeSEwan D. Milne scsi_report_sense(sdev, &sshdr); 455279afdfeSEwan D. Milne 4561da177e4SLinus Torvalds if (scsi_sense_is_deferred(&sshdr)) 4571da177e4SLinus Torvalds return NEEDS_RETRY; 4581da177e4SLinus Torvalds 459ee14c674SChristoph Hellwig if (sdev->handler && sdev->handler->check_sense) { 460a6a8d9f8SChandra Seetharaman int rc; 461a6a8d9f8SChandra Seetharaman 462ee14c674SChristoph Hellwig rc = sdev->handler->check_sense(sdev, &sshdr); 463a6a8d9f8SChandra Seetharaman if (rc != SCSI_RETURN_NOT_HANDLED) 464a6a8d9f8SChandra Seetharaman return rc; 465a6a8d9f8SChandra Seetharaman /* handler does not care. Drop down to default handling */ 466a6a8d9f8SChandra Seetharaman } 467a6a8d9f8SChandra Seetharaman 468e925cc43SChristoph Hellwig if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) 469e925cc43SChristoph Hellwig /* 470e925cc43SChristoph Hellwig * nasty: for mid-layer issued TURs, we need to return the 471e925cc43SChristoph Hellwig * actual sense data without any recovery attempt. For eh 472e925cc43SChristoph Hellwig * issued ones, we need to try to recover and interpret 473e925cc43SChristoph Hellwig */ 474e925cc43SChristoph Hellwig return SUCCESS; 475e925cc43SChristoph Hellwig 4761da177e4SLinus Torvalds /* 4771da177e4SLinus Torvalds * Previous logic looked for FILEMARK, EOM or ILI which are 4781da177e4SLinus Torvalds * mainly associated with tapes and returned SUCCESS. 4791da177e4SLinus Torvalds */ 4801da177e4SLinus Torvalds if (sshdr.response_code == 0x70) { 4811da177e4SLinus Torvalds /* fixed format */ 4821da177e4SLinus Torvalds if (scmd->sense_buffer[2] & 0xe0) 4831da177e4SLinus Torvalds return SUCCESS; 4841da177e4SLinus Torvalds } else { 4851da177e4SLinus Torvalds /* 4861da177e4SLinus Torvalds * descriptor format: look for "stream commands sense data 4871da177e4SLinus Torvalds * descriptor" (see SSC-3). Assume single sense data 4881da177e4SLinus Torvalds * descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG. 4891da177e4SLinus Torvalds */ 4901da177e4SLinus Torvalds if ((sshdr.additional_length > 3) && 4911da177e4SLinus Torvalds (scmd->sense_buffer[8] == 0x4) && 4921da177e4SLinus Torvalds (scmd->sense_buffer[11] & 0xe0)) 4931da177e4SLinus Torvalds return SUCCESS; 4941da177e4SLinus Torvalds } 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds switch (sshdr.sense_key) { 4971da177e4SLinus Torvalds case NO_SENSE: 4981da177e4SLinus Torvalds return SUCCESS; 4991da177e4SLinus Torvalds case RECOVERED_ERROR: 5001da177e4SLinus Torvalds return /* soft_error */ SUCCESS; 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds case ABORTED_COMMAND: 503511e44f4SMartin K. Petersen if (sshdr.asc == 0x10) /* DIF */ 504511e44f4SMartin K. Petersen return SUCCESS; 505511e44f4SMartin K. Petersen 5061da177e4SLinus Torvalds return NEEDS_RETRY; 5071da177e4SLinus Torvalds case NOT_READY: 5081da177e4SLinus Torvalds case UNIT_ATTENTION: 5091da177e4SLinus Torvalds /* 5101da177e4SLinus Torvalds * if we are expecting a cc/ua because of a bus reset that we 5111da177e4SLinus Torvalds * performed, treat this just as a retry. otherwise this is 5121da177e4SLinus Torvalds * information that we should pass up to the upper-level driver 5131da177e4SLinus Torvalds * so that we can deal with it there. 5141da177e4SLinus Torvalds */ 5151da177e4SLinus Torvalds if (scmd->device->expecting_cc_ua) { 516dfcf7775STARUISI Hiroaki /* 517dfcf7775STARUISI Hiroaki * Because some device does not queue unit 518dfcf7775STARUISI Hiroaki * attentions correctly, we carefully check 519dfcf7775STARUISI Hiroaki * additional sense code and qualifier so as 520dfcf7775STARUISI Hiroaki * not to squash media change unit attention. 521dfcf7775STARUISI Hiroaki */ 522dfcf7775STARUISI Hiroaki if (sshdr.asc != 0x28 || sshdr.ascq != 0x00) { 5231da177e4SLinus Torvalds scmd->device->expecting_cc_ua = 0; 5241da177e4SLinus Torvalds return NEEDS_RETRY; 5251da177e4SLinus Torvalds } 526dfcf7775STARUISI Hiroaki } 5271da177e4SLinus Torvalds /* 528279afdfeSEwan D. Milne * we might also expect a cc/ua if another LUN on the target 529279afdfeSEwan D. Milne * reported a UA with an ASC/ASCQ of 3F 0E - 530279afdfeSEwan D. Milne * REPORTED LUNS DATA HAS CHANGED. 531279afdfeSEwan D. Milne */ 532279afdfeSEwan D. Milne if (scmd->device->sdev_target->expecting_lun_change && 533279afdfeSEwan D. Milne sshdr.asc == 0x3f && sshdr.ascq == 0x0e) 534279afdfeSEwan D. Milne return NEEDS_RETRY; 535279afdfeSEwan D. Milne /* 5361da177e4SLinus Torvalds * if the device is in the process of becoming ready, we 5371da177e4SLinus Torvalds * should retry. 5381da177e4SLinus Torvalds */ 5391da177e4SLinus Torvalds if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01)) 5401da177e4SLinus Torvalds return NEEDS_RETRY; 5411da177e4SLinus Torvalds /* 5421da177e4SLinus Torvalds * if the device is not started, we need to wake 5431da177e4SLinus Torvalds * the error handler to start the motor 5441da177e4SLinus Torvalds */ 5451da177e4SLinus Torvalds if (scmd->device->allow_restart && 5461da177e4SLinus Torvalds (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) 5471da177e4SLinus Torvalds return FAILED; 54877a42297SJames Bottomley /* 54902e031cbSChristoph Hellwig * Pass the UA upwards for a determination in the completion 55002e031cbSChristoph Hellwig * functions. 55177a42297SJames Bottomley */ 5521da177e4SLinus Torvalds return SUCCESS; 5531da177e4SLinus Torvalds 55463583ccaSHannes Reinecke /* these are not supported */ 555a9d6ceb8SHannes Reinecke case DATA_PROTECT: 556a9d6ceb8SHannes Reinecke if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) { 557a9d6ceb8SHannes Reinecke /* Thin provisioning hard threshold reached */ 558a9d6ceb8SHannes Reinecke set_host_byte(scmd, DID_ALLOC_FAILURE); 559a9d6ceb8SHannes Reinecke return SUCCESS; 560a9d6ceb8SHannes Reinecke } 5613bf2ff67SBart Van Assche /* FALLTHROUGH */ 5621da177e4SLinus Torvalds case COPY_ABORTED: 5631da177e4SLinus Torvalds case VOLUME_OVERFLOW: 5641da177e4SLinus Torvalds case MISCOMPARE: 56563583ccaSHannes Reinecke case BLANK_CHECK: 56687f14e65SHannes Reinecke set_host_byte(scmd, DID_TARGET_FAILURE); 56787f14e65SHannes Reinecke return SUCCESS; 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds case MEDIUM_ERROR: 570fd1b494dSLuben Tuikov if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ 571fd1b494dSLuben Tuikov sshdr.asc == 0x13 || /* AMNF DATA FIELD */ 572fd1b494dSLuben Tuikov sshdr.asc == 0x14) { /* RECORD NOT FOUND */ 5737e782af5SHannes Reinecke set_host_byte(scmd, DID_MEDIUM_ERROR); 57487f14e65SHannes Reinecke return SUCCESS; 575fd1b494dSLuben Tuikov } 5761da177e4SLinus Torvalds return NEEDS_RETRY; 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds case HARDWARE_ERROR: 5791da177e4SLinus Torvalds if (scmd->device->retry_hwerror) 580bb0003c1SMike Anderson return ADD_TO_MLQUEUE; 5811da177e4SLinus Torvalds else 58287f14e65SHannes Reinecke set_host_byte(scmd, DID_TARGET_FAILURE); 5833bf2ff67SBart Van Assche /* FALLTHROUGH */ 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds case ILLEGAL_REQUEST: 58647ac56dbSMike Snitzer if (sshdr.asc == 0x20 || /* Invalid command operation code */ 58747ac56dbSMike Snitzer sshdr.asc == 0x21 || /* Logical block address out of range */ 588a8bbb2abSHannes Reinecke sshdr.asc == 0x22 || /* Invalid function */ 58947ac56dbSMike Snitzer sshdr.asc == 0x24 || /* Invalid field in cdb */ 59047ac56dbSMike Snitzer sshdr.asc == 0x26) { /* Parameter value invalid */ 59187f14e65SHannes Reinecke set_host_byte(scmd, DID_TARGET_FAILURE); 59247ac56dbSMike Snitzer } 59347ac56dbSMike Snitzer return SUCCESS; 59447ac56dbSMike Snitzer 5951da177e4SLinus Torvalds default: 5961da177e4SLinus Torvalds return SUCCESS; 5971da177e4SLinus Torvalds } 5981da177e4SLinus Torvalds } 5993852e373SHannes Reinecke EXPORT_SYMBOL_GPL(scsi_check_sense); 6001da177e4SLinus Torvalds 6014a84067dSVasu Dev static void scsi_handle_queue_ramp_up(struct scsi_device *sdev) 6024a84067dSVasu Dev { 6034a84067dSVasu Dev struct scsi_host_template *sht = sdev->host->hostt; 6044a84067dSVasu Dev struct scsi_device *tmp_sdev; 6054a84067dSVasu Dev 606c40ecc12SChristoph Hellwig if (!sht->track_queue_depth || 6074a84067dSVasu Dev sdev->queue_depth >= sdev->max_queue_depth) 6084a84067dSVasu Dev return; 6094a84067dSVasu Dev 6104a84067dSVasu Dev if (time_before(jiffies, 6114a84067dSVasu Dev sdev->last_queue_ramp_up + sdev->queue_ramp_up_period)) 6124a84067dSVasu Dev return; 6134a84067dSVasu Dev 6144a84067dSVasu Dev if (time_before(jiffies, 6154a84067dSVasu Dev sdev->last_queue_full_time + sdev->queue_ramp_up_period)) 6164a84067dSVasu Dev return; 6174a84067dSVasu Dev 6184a84067dSVasu Dev /* 6194a84067dSVasu Dev * Walk all devices of a target and do 6204a84067dSVasu Dev * ramp up on them. 6214a84067dSVasu Dev */ 6224a84067dSVasu Dev shost_for_each_device(tmp_sdev, sdev->host) { 6234a84067dSVasu Dev if (tmp_sdev->channel != sdev->channel || 6244a84067dSVasu Dev tmp_sdev->id != sdev->id || 6254a84067dSVasu Dev tmp_sdev->queue_depth == sdev->max_queue_depth) 6264a84067dSVasu Dev continue; 627c40ecc12SChristoph Hellwig 628db5ed4dfSChristoph Hellwig scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1); 6294a84067dSVasu Dev sdev->last_queue_ramp_up = jiffies; 6304a84067dSVasu Dev } 6314a84067dSVasu Dev } 6324a84067dSVasu Dev 63342a6a918SMike Christie static void scsi_handle_queue_full(struct scsi_device *sdev) 63442a6a918SMike Christie { 63542a6a918SMike Christie struct scsi_host_template *sht = sdev->host->hostt; 63642a6a918SMike Christie struct scsi_device *tmp_sdev; 63742a6a918SMike Christie 638c40ecc12SChristoph Hellwig if (!sht->track_queue_depth) 63942a6a918SMike Christie return; 64042a6a918SMike Christie 64142a6a918SMike Christie shost_for_each_device(tmp_sdev, sdev->host) { 64242a6a918SMike Christie if (tmp_sdev->channel != sdev->channel || 64342a6a918SMike Christie tmp_sdev->id != sdev->id) 64442a6a918SMike Christie continue; 64542a6a918SMike Christie /* 64642a6a918SMike Christie * We do not know the number of commands that were at 64742a6a918SMike Christie * the device when we got the queue full so we start 64842a6a918SMike Christie * from the highest possible value and work our way down. 64942a6a918SMike Christie */ 650c40ecc12SChristoph Hellwig scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1); 65142a6a918SMike Christie } 65242a6a918SMike Christie } 65342a6a918SMike Christie 6541da177e4SLinus Torvalds /** 6551da177e4SLinus Torvalds * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD. 6561da177e4SLinus Torvalds * @scmd: SCSI cmd to examine. 6571da177e4SLinus Torvalds * 6581da177e4SLinus Torvalds * Notes: 6591da177e4SLinus Torvalds * This is *only* called when we are examining the status of commands 6601da177e4SLinus Torvalds * queued during error recovery. the main difference here is that we 6611da177e4SLinus Torvalds * don't allow for the possibility of retries here, and we are a lot 6621da177e4SLinus Torvalds * more restrictive about what we consider acceptable. 663dc8875e1SRandy Dunlap */ 6641da177e4SLinus Torvalds static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) 6651da177e4SLinus Torvalds { 6661da177e4SLinus Torvalds /* 6671da177e4SLinus Torvalds * first check the host byte, to see if there is anything in there 6681da177e4SLinus Torvalds * that would indicate what we need to do. 6691da177e4SLinus Torvalds */ 6701da177e4SLinus Torvalds if (host_byte(scmd->result) == DID_RESET) { 6711da177e4SLinus Torvalds /* 6721da177e4SLinus Torvalds * rats. we are already in the error handler, so we now 6731da177e4SLinus Torvalds * get to try and figure out what to do next. if the sense 6741da177e4SLinus Torvalds * is valid, we have a pretty good idea of what to do. 6751da177e4SLinus Torvalds * if not, we mark it as FAILED. 6761da177e4SLinus Torvalds */ 6771da177e4SLinus Torvalds return scsi_check_sense(scmd); 6781da177e4SLinus Torvalds } 6791da177e4SLinus Torvalds if (host_byte(scmd->result) != DID_OK) 6801da177e4SLinus Torvalds return FAILED; 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds /* 6831da177e4SLinus Torvalds * next, check the message byte. 6841da177e4SLinus Torvalds */ 6851da177e4SLinus Torvalds if (msg_byte(scmd->result) != COMMAND_COMPLETE) 6861da177e4SLinus Torvalds return FAILED; 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds /* 6891da177e4SLinus Torvalds * now, check the status byte to see if this indicates 6901da177e4SLinus Torvalds * anything special. 6911da177e4SLinus Torvalds */ 6921da177e4SLinus Torvalds switch (status_byte(scmd->result)) { 6931da177e4SLinus Torvalds case GOOD: 6944a84067dSVasu Dev scsi_handle_queue_ramp_up(scmd->device); 6953bf2ff67SBart Van Assche /* FALLTHROUGH */ 6961da177e4SLinus Torvalds case COMMAND_TERMINATED: 6971da177e4SLinus Torvalds return SUCCESS; 6981da177e4SLinus Torvalds case CHECK_CONDITION: 6991da177e4SLinus Torvalds return scsi_check_sense(scmd); 7001da177e4SLinus Torvalds case CONDITION_GOOD: 7011da177e4SLinus Torvalds case INTERMEDIATE_GOOD: 7021da177e4SLinus Torvalds case INTERMEDIATE_C_GOOD: 7031da177e4SLinus Torvalds /* 7041da177e4SLinus Torvalds * who knows? FIXME(eric) 7051da177e4SLinus Torvalds */ 7061da177e4SLinus Torvalds return SUCCESS; 7075f91bb05SMichael Reed case RESERVATION_CONFLICT: 70867110dfdSJames Bottomley if (scmd->cmnd[0] == TEST_UNIT_READY) 70967110dfdSJames Bottomley /* it is a success, we probed the device and 71067110dfdSJames Bottomley * found it */ 7115f91bb05SMichael Reed return SUCCESS; 71267110dfdSJames Bottomley /* otherwise, we failed to send the command */ 71367110dfdSJames Bottomley return FAILED; 7141da177e4SLinus Torvalds case QUEUE_FULL: 71542a6a918SMike Christie scsi_handle_queue_full(scmd->device); 71642a6a918SMike Christie /* fall through */ 71742a6a918SMike Christie case BUSY: 7183eb3a928SHannes Reinecke return NEEDS_RETRY; 7191da177e4SLinus Torvalds default: 7201da177e4SLinus Torvalds return FAILED; 7211da177e4SLinus Torvalds } 7221da177e4SLinus Torvalds return FAILED; 7231da177e4SLinus Torvalds } 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds /** 7261da177e4SLinus Torvalds * scsi_eh_done - Completion function for error handling. 7271da177e4SLinus Torvalds * @scmd: Cmd that is done. 728dc8875e1SRandy Dunlap */ 7291da177e4SLinus Torvalds static void scsi_eh_done(struct scsi_cmnd *scmd) 7301da177e4SLinus Torvalds { 73185631672SMichael Reed struct completion *eh_action; 73285631672SMichael Reed 73391921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 734470613b4SHannes Reinecke "%s result: %x\n", __func__, scmd->result)); 73585631672SMichael Reed 73685631672SMichael Reed eh_action = scmd->device->host->eh_action; 73785631672SMichael Reed if (eh_action) 73885631672SMichael Reed complete(eh_action); 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds /** 742292148f8SBrian King * scsi_try_host_reset - ask host adapter to reset itself 743c2b3ebd0SGeert Uytterhoeven * @scmd: SCSI cmd to send host reset. 744dc8875e1SRandy Dunlap */ 745292148f8SBrian King static int scsi_try_host_reset(struct scsi_cmnd *scmd) 746292148f8SBrian King { 747292148f8SBrian King unsigned long flags; 748292148f8SBrian King int rtn; 7490bf8c869SJesper Juhl struct Scsi_Host *host = scmd->device->host; 7500bf8c869SJesper Juhl struct scsi_host_template *hostt = host->hostt; 751292148f8SBrian King 75291921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 75391921e01SHannes Reinecke shost_printk(KERN_INFO, host, "Snd Host RST\n")); 754292148f8SBrian King 7550bf8c869SJesper Juhl if (!hostt->eh_host_reset_handler) 756292148f8SBrian King return FAILED; 757292148f8SBrian King 7580bf8c869SJesper Juhl rtn = hostt->eh_host_reset_handler(scmd); 759292148f8SBrian King 760292148f8SBrian King if (rtn == SUCCESS) { 7610bf8c869SJesper Juhl if (!hostt->skip_settle_delay) 762292148f8SBrian King ssleep(HOST_RESET_SETTLE_TIME); 7630bf8c869SJesper Juhl spin_lock_irqsave(host->host_lock, flags); 7640bf8c869SJesper Juhl scsi_report_bus_reset(host, scmd_channel(scmd)); 7650bf8c869SJesper Juhl spin_unlock_irqrestore(host->host_lock, flags); 766292148f8SBrian King } 767292148f8SBrian King 768292148f8SBrian King return rtn; 769292148f8SBrian King } 770292148f8SBrian King 771292148f8SBrian King /** 772292148f8SBrian King * scsi_try_bus_reset - ask host to perform a bus reset 773292148f8SBrian King * @scmd: SCSI cmd to send bus reset. 774dc8875e1SRandy Dunlap */ 775292148f8SBrian King static int scsi_try_bus_reset(struct scsi_cmnd *scmd) 776292148f8SBrian King { 777292148f8SBrian King unsigned long flags; 778292148f8SBrian King int rtn; 7790bf8c869SJesper Juhl struct Scsi_Host *host = scmd->device->host; 7800bf8c869SJesper Juhl struct scsi_host_template *hostt = host->hostt; 781292148f8SBrian King 78291921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 78391921e01SHannes Reinecke "%s: Snd Bus RST\n", __func__)); 784292148f8SBrian King 7850bf8c869SJesper Juhl if (!hostt->eh_bus_reset_handler) 786292148f8SBrian King return FAILED; 787292148f8SBrian King 7880bf8c869SJesper Juhl rtn = hostt->eh_bus_reset_handler(scmd); 789292148f8SBrian King 790292148f8SBrian King if (rtn == SUCCESS) { 7910bf8c869SJesper Juhl if (!hostt->skip_settle_delay) 792292148f8SBrian King ssleep(BUS_RESET_SETTLE_TIME); 7930bf8c869SJesper Juhl spin_lock_irqsave(host->host_lock, flags); 7940bf8c869SJesper Juhl scsi_report_bus_reset(host, scmd_channel(scmd)); 7950bf8c869SJesper Juhl spin_unlock_irqrestore(host->host_lock, flags); 796292148f8SBrian King } 797292148f8SBrian King 798292148f8SBrian King return rtn; 799292148f8SBrian King } 800292148f8SBrian King 80130bd7df8SMike Christie static void __scsi_report_device_reset(struct scsi_device *sdev, void *data) 80230bd7df8SMike Christie { 80330bd7df8SMike Christie sdev->was_reset = 1; 80430bd7df8SMike Christie sdev->expecting_cc_ua = 1; 80530bd7df8SMike Christie } 80630bd7df8SMike Christie 80730bd7df8SMike Christie /** 80830bd7df8SMike Christie * scsi_try_target_reset - Ask host to perform a target reset 80930bd7df8SMike Christie * @scmd: SCSI cmd used to send a target reset 81030bd7df8SMike Christie * 81130bd7df8SMike Christie * Notes: 81230bd7df8SMike Christie * There is no timeout for this operation. if this operation is 81330bd7df8SMike Christie * unreliable for a given host, then the host itself needs to put a 81430bd7df8SMike Christie * timer on it, and set the host back to a consistent state prior to 81530bd7df8SMike Christie * returning. 81630bd7df8SMike Christie */ 81730bd7df8SMike Christie static int scsi_try_target_reset(struct scsi_cmnd *scmd) 81830bd7df8SMike Christie { 81930bd7df8SMike Christie unsigned long flags; 82030bd7df8SMike Christie int rtn; 8210bf8c869SJesper Juhl struct Scsi_Host *host = scmd->device->host; 8220bf8c869SJesper Juhl struct scsi_host_template *hostt = host->hostt; 82330bd7df8SMike Christie 8240bf8c869SJesper Juhl if (!hostt->eh_target_reset_handler) 82530bd7df8SMike Christie return FAILED; 82630bd7df8SMike Christie 8270bf8c869SJesper Juhl rtn = hostt->eh_target_reset_handler(scmd); 82830bd7df8SMike Christie if (rtn == SUCCESS) { 8290bf8c869SJesper Juhl spin_lock_irqsave(host->host_lock, flags); 83030bd7df8SMike Christie __starget_for_each_device(scsi_target(scmd->device), NULL, 83130bd7df8SMike Christie __scsi_report_device_reset); 8320bf8c869SJesper Juhl spin_unlock_irqrestore(host->host_lock, flags); 83330bd7df8SMike Christie } 83430bd7df8SMike Christie 83530bd7df8SMike Christie return rtn; 83630bd7df8SMike Christie } 83730bd7df8SMike Christie 838292148f8SBrian King /** 839292148f8SBrian King * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev 840292148f8SBrian King * @scmd: SCSI cmd used to send BDR 841292148f8SBrian King * 842292148f8SBrian King * Notes: 843292148f8SBrian King * There is no timeout for this operation. if this operation is 844292148f8SBrian King * unreliable for a given host, then the host itself needs to put a 845292148f8SBrian King * timer on it, and set the host back to a consistent state prior to 846292148f8SBrian King * returning. 847dc8875e1SRandy Dunlap */ 848292148f8SBrian King static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) 849292148f8SBrian King { 850292148f8SBrian King int rtn; 8510bf8c869SJesper Juhl struct scsi_host_template *hostt = scmd->device->host->hostt; 852292148f8SBrian King 8530bf8c869SJesper Juhl if (!hostt->eh_device_reset_handler) 854292148f8SBrian King return FAILED; 855292148f8SBrian King 8560bf8c869SJesper Juhl rtn = hostt->eh_device_reset_handler(scmd); 85730bd7df8SMike Christie if (rtn == SUCCESS) 85830bd7df8SMike Christie __scsi_report_device_reset(scmd->device, NULL); 859292148f8SBrian King return rtn; 860292148f8SBrian King } 861292148f8SBrian King 862883a030fSHannes Reinecke /** 863883a030fSHannes Reinecke * scsi_try_to_abort_cmd - Ask host to abort a SCSI command 8646583f6fbSRandy Dunlap * @hostt: SCSI driver host template 865883a030fSHannes Reinecke * @scmd: SCSI cmd used to send a target reset 866883a030fSHannes Reinecke * 867883a030fSHannes Reinecke * Return value: 868883a030fSHannes Reinecke * SUCCESS, FAILED, or FAST_IO_FAIL 869883a030fSHannes Reinecke * 870883a030fSHannes Reinecke * Notes: 871883a030fSHannes Reinecke * SUCCESS does not necessarily indicate that the command 872883a030fSHannes Reinecke * has been aborted; it only indicates that the LLDDs 873883a030fSHannes Reinecke * has cleared all references to that command. 874883a030fSHannes Reinecke * LLDDs should return FAILED only if an abort was required 875883a030fSHannes Reinecke * but could not be executed. LLDDs should return FAST_IO_FAIL 876883a030fSHannes Reinecke * if the device is temporarily unavailable (eg due to a 877883a030fSHannes Reinecke * link down on FibreChannel) 878883a030fSHannes Reinecke */ 879883a030fSHannes Reinecke static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, 880883a030fSHannes Reinecke struct scsi_cmnd *scmd) 881292148f8SBrian King { 8820bf8c869SJesper Juhl if (!hostt->eh_abort_handler) 883292148f8SBrian King return FAILED; 884292148f8SBrian King 8850bf8c869SJesper Juhl return hostt->eh_abort_handler(scmd); 886292148f8SBrian King } 887292148f8SBrian King 888292148f8SBrian King static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) 889292148f8SBrian King { 8900bf8c869SJesper Juhl if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS) 891292148f8SBrian King if (scsi_try_bus_device_reset(scmd) != SUCCESS) 89230bd7df8SMike Christie if (scsi_try_target_reset(scmd) != SUCCESS) 893292148f8SBrian King if (scsi_try_bus_reset(scmd) != SUCCESS) 894292148f8SBrian King scsi_try_host_reset(scmd); 895292148f8SBrian King } 896292148f8SBrian King 897292148f8SBrian King /** 8983b729f76SSantosh Y * scsi_eh_prep_cmnd - Save a scsi command info as part of error recovery 8992dc611deSChristoph Hellwig * @scmd: SCSI command structure to hijack 900e1c23468SBoaz Harrosh * @ses: structure to save restore information 90155db6c1bSBoaz Harrosh * @cmnd: CDB to send. Can be NULL if no new cmnd is needed 90264a87b24SBoaz Harrosh * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) 90355db6c1bSBoaz Harrosh * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) 9042dc611deSChristoph Hellwig * 905e1c23468SBoaz Harrosh * This function is used to save a scsi command information before re-execution 90655db6c1bSBoaz Harrosh * as part of the error recovery process. If @sense_bytes is 0 the command 90755db6c1bSBoaz Harrosh * sent must be one that does not transfer any data. If @sense_bytes != 0 90855db6c1bSBoaz Harrosh * @cmnd is ignored and this functions sets up a REQUEST_SENSE command 90955db6c1bSBoaz Harrosh * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer. 910dc8875e1SRandy Dunlap */ 911e1c23468SBoaz Harrosh void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, 912e1c23468SBoaz Harrosh unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) 9131da177e4SLinus Torvalds { 914f59114b7S struct scsi_device *sdev = scmd->device; 9151da177e4SLinus Torvalds 916631c228cSChristoph Hellwig /* 917631c228cSChristoph Hellwig * We need saved copies of a number of fields - this is because 918631c228cSChristoph Hellwig * error handling may need to overwrite these with different values 919631c228cSChristoph Hellwig * to run different commands, and once error handling is complete, 920631c228cSChristoph Hellwig * we will need to restore these values prior to running the actual 921631c228cSChristoph Hellwig * command. 922631c228cSChristoph Hellwig */ 923e1c23468SBoaz Harrosh ses->cmd_len = scmd->cmd_len; 92464a87b24SBoaz Harrosh ses->cmnd = scmd->cmnd; 925e1c23468SBoaz Harrosh ses->data_direction = scmd->sc_data_direction; 92630b0c37bSBoaz Harrosh ses->sdb = scmd->sdb; 9276f9a35e2SBoaz Harrosh ses->next_rq = scmd->request->next_rq; 928e1c23468SBoaz Harrosh ses->result = scmd->result; 92912265709SAlan Stern ses->underflow = scmd->underflow; 930db007fc5SMartin K. Petersen ses->prot_op = scmd->prot_op; 9318e8c9d01SHannes Reinecke ses->eh_eflags = scmd->eh_eflags; 932631c228cSChristoph Hellwig 933db007fc5SMartin K. Petersen scmd->prot_op = SCSI_PROT_NORMAL; 934c69e6f81SJames Bottomley scmd->eh_eflags = 0; 93564a87b24SBoaz Harrosh scmd->cmnd = ses->eh_cmnd; 93664a87b24SBoaz Harrosh memset(scmd->cmnd, 0, BLK_MAX_CDB); 93730b0c37bSBoaz Harrosh memset(&scmd->sdb, 0, sizeof(scmd->sdb)); 9386f9a35e2SBoaz Harrosh scmd->request->next_rq = NULL; 939644373a4SAlan Stern scmd->result = 0; 94030b0c37bSBoaz Harrosh 94155db6c1bSBoaz Harrosh if (sense_bytes) { 94230b0c37bSBoaz Harrosh scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE, 94330b0c37bSBoaz Harrosh sense_bytes); 944e1c23468SBoaz Harrosh sg_init_one(&ses->sense_sgl, scmd->sense_buffer, 94530b0c37bSBoaz Harrosh scmd->sdb.length); 94630b0c37bSBoaz Harrosh scmd->sdb.table.sgl = &ses->sense_sgl; 94755db6c1bSBoaz Harrosh scmd->sc_data_direction = DMA_FROM_DEVICE; 9480c958eccSTony Battersby scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1; 94955db6c1bSBoaz Harrosh scmd->cmnd[0] = REQUEST_SENSE; 95030b0c37bSBoaz Harrosh scmd->cmnd[4] = scmd->sdb.length; 95155db6c1bSBoaz Harrosh scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); 952631c228cSChristoph Hellwig } else { 953631c228cSChristoph Hellwig scmd->sc_data_direction = DMA_NONE; 95455db6c1bSBoaz Harrosh if (cmnd) { 95564a87b24SBoaz Harrosh BUG_ON(cmnd_size > BLK_MAX_CDB); 95655db6c1bSBoaz Harrosh memcpy(scmd->cmnd, cmnd, cmnd_size); 95755db6c1bSBoaz Harrosh scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); 95855db6c1bSBoaz Harrosh } 959631c228cSChristoph Hellwig } 960631c228cSChristoph Hellwig 961631c228cSChristoph Hellwig scmd->underflow = 0; 962631c228cSChristoph Hellwig 96355db6c1bSBoaz Harrosh if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN) 9641da177e4SLinus Torvalds scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | 965f59114b7S (sdev->lun << 5 & 0xe0); 9661da177e4SLinus Torvalds 967631c228cSChristoph Hellwig /* 968631c228cSChristoph Hellwig * Zero the sense buffer. The scsi spec mandates that any 969631c228cSChristoph Hellwig * untransferred sense data should be interpreted as being zero. 970631c228cSChristoph Hellwig */ 971b80ca4f7SFUJITA Tomonori memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 972e1c23468SBoaz Harrosh } 973e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_prep_cmnd); 974631c228cSChristoph Hellwig 975e1c23468SBoaz Harrosh /** 9763b729f76SSantosh Y * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recovery 977e1c23468SBoaz Harrosh * @scmd: SCSI command structure to restore 978477e608cSBartlomiej Zolnierkiewicz * @ses: saved information from a coresponding call to scsi_eh_prep_cmnd 979e1c23468SBoaz Harrosh * 980477e608cSBartlomiej Zolnierkiewicz * Undo any damage done by above scsi_eh_prep_cmnd(). 981dc8875e1SRandy Dunlap */ 982e1c23468SBoaz Harrosh void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) 983e1c23468SBoaz Harrosh { 984e1c23468SBoaz Harrosh /* 985e1c23468SBoaz Harrosh * Restore original data 986e1c23468SBoaz Harrosh */ 987e1c23468SBoaz Harrosh scmd->cmd_len = ses->cmd_len; 98864a87b24SBoaz Harrosh scmd->cmnd = ses->cmnd; 989e1c23468SBoaz Harrosh scmd->sc_data_direction = ses->data_direction; 99030b0c37bSBoaz Harrosh scmd->sdb = ses->sdb; 9916f9a35e2SBoaz Harrosh scmd->request->next_rq = ses->next_rq; 992e1c23468SBoaz Harrosh scmd->result = ses->result; 99312265709SAlan Stern scmd->underflow = ses->underflow; 994db007fc5SMartin K. Petersen scmd->prot_op = ses->prot_op; 9958e8c9d01SHannes Reinecke scmd->eh_eflags = ses->eh_eflags; 996e1c23468SBoaz Harrosh } 997e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_restore_cmnd); 998e1c23468SBoaz Harrosh 999e1c23468SBoaz Harrosh /** 10003b729f76SSantosh Y * scsi_send_eh_cmnd - submit a scsi command as part of error recovery 1001e1c23468SBoaz Harrosh * @scmd: SCSI command structure to hijack 1002e1c23468SBoaz Harrosh * @cmnd: CDB to send 1003e1c23468SBoaz Harrosh * @cmnd_size: size in bytes of @cmnd 1004e1c23468SBoaz Harrosh * @timeout: timeout for this request 1005e1c23468SBoaz Harrosh * @sense_bytes: size of sense data to copy or 0 1006e1c23468SBoaz Harrosh * 1007e1c23468SBoaz Harrosh * This function is used to send a scsi command down to a target device 1008e1c23468SBoaz Harrosh * as part of the error recovery process. See also scsi_eh_prep_cmnd() above. 1009e1c23468SBoaz Harrosh * 1010e1c23468SBoaz Harrosh * Return value: 1011e1c23468SBoaz Harrosh * SUCCESS or FAILED or NEEDS_RETRY 1012dc8875e1SRandy Dunlap */ 1013e1c23468SBoaz Harrosh static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, 1014e1c23468SBoaz Harrosh int cmnd_size, int timeout, unsigned sense_bytes) 1015e1c23468SBoaz Harrosh { 1016e1c23468SBoaz Harrosh struct scsi_device *sdev = scmd->device; 1017e1c23468SBoaz Harrosh struct Scsi_Host *shost = sdev->host; 1018e1c23468SBoaz Harrosh DECLARE_COMPLETION_ONSTACK(done); 1019fc73648aSHannes Reinecke unsigned long timeleft = timeout; 1020e1c23468SBoaz Harrosh struct scsi_eh_save ses; 1021fc73648aSHannes Reinecke const unsigned long stall_for = msecs_to_jiffies(100); 1022e1c23468SBoaz Harrosh int rtn; 1023e1c23468SBoaz Harrosh 1024fc73648aSHannes Reinecke retry: 1025e1c23468SBoaz Harrosh scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); 10267dfdc9a5SChristoph Hellwig shost->eh_action = &done; 10271da177e4SLinus Torvalds 10281da177e4SLinus Torvalds scsi_log_send(scmd); 1029f281233dSJeff Garzik scmd->scsi_done = scsi_eh_done; 1030fc73648aSHannes Reinecke rtn = shost->hostt->queuecommand(shost, scmd); 1031fc73648aSHannes Reinecke if (rtn) { 1032fc73648aSHannes Reinecke if (timeleft > stall_for) { 1033fc73648aSHannes Reinecke scsi_eh_restore_cmnd(scmd, &ses); 1034fc73648aSHannes Reinecke timeleft -= stall_for; 1035fc73648aSHannes Reinecke msleep(jiffies_to_msecs(stall_for)); 1036fc73648aSHannes Reinecke goto retry; 1037fc73648aSHannes Reinecke } 1038fc73648aSHannes Reinecke /* signal not to enter either branch of the if () below */ 1039fc73648aSHannes Reinecke timeleft = 0; 1040511833acSAlan Stern rtn = FAILED; 1041fc73648aSHannes Reinecke } else { 10427dfdc9a5SChristoph Hellwig timeleft = wait_for_completion_timeout(&done, timeout); 1043ac61d195SHannes Reinecke rtn = SUCCESS; 1044fc73648aSHannes Reinecke } 10451da177e4SLinus Torvalds 10467dfdc9a5SChristoph Hellwig shost->eh_action = NULL; 10471da177e4SLinus Torvalds 1048fc73648aSHannes Reinecke scsi_log_completion(scmd, rtn); 10497dfdc9a5SChristoph Hellwig 105091921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 1051470613b4SHannes Reinecke "%s timeleft: %ld\n", 1052470613b4SHannes Reinecke __func__, timeleft)); 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds /* 1055fc73648aSHannes Reinecke * If there is time left scsi_eh_done got called, and we will examine 1056fc73648aSHannes Reinecke * the actual status codes to see whether the command actually did 1057fc73648aSHannes Reinecke * complete normally, else if we have a zero return and no time left, 1058fc73648aSHannes Reinecke * the command must still be pending, so abort it and return FAILED. 1059fc73648aSHannes Reinecke * If we never actually managed to issue the command, because 1060fc73648aSHannes Reinecke * ->queuecommand() kept returning non zero, use the rtn = FAILED 1061fc73648aSHannes Reinecke * value above (so don't execute either branch of the if) 10621da177e4SLinus Torvalds */ 10637dfdc9a5SChristoph Hellwig if (timeleft) { 10641da177e4SLinus Torvalds rtn = scsi_eh_completed_normally(scmd); 106591921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 106691921e01SHannes Reinecke "%s: scsi_eh_completed_normally %x\n", __func__, rtn)); 10677dfdc9a5SChristoph Hellwig 10681da177e4SLinus Torvalds switch (rtn) { 10691da177e4SLinus Torvalds case SUCCESS: 10701da177e4SLinus Torvalds case NEEDS_RETRY: 10711da177e4SLinus Torvalds case FAILED: 10721da177e4SLinus Torvalds break; 10736e883b0eSHannes Reinecke case ADD_TO_MLQUEUE: 10746e883b0eSHannes Reinecke rtn = NEEDS_RETRY; 10756e883b0eSHannes Reinecke break; 10761da177e4SLinus Torvalds default: 10771da177e4SLinus Torvalds rtn = FAILED; 10781da177e4SLinus Torvalds break; 10791da177e4SLinus Torvalds } 1080511833acSAlan Stern } else if (rtn != FAILED) { 1081292148f8SBrian King scsi_abort_eh_cmnd(scmd); 10827dfdc9a5SChristoph Hellwig rtn = FAILED; 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 1085e1c23468SBoaz Harrosh scsi_eh_restore_cmnd(scmd, &ses); 108618a4d0a2SMartin K. Petersen 10871da177e4SLinus Torvalds return rtn; 10881da177e4SLinus Torvalds } 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds /** 10911da177e4SLinus Torvalds * scsi_request_sense - Request sense data from a particular target. 10921da177e4SLinus Torvalds * @scmd: SCSI cmd for request sense. 10931da177e4SLinus Torvalds * 10941da177e4SLinus Torvalds * Notes: 10951da177e4SLinus Torvalds * Some hosts automatically obtain this information, others require 10961da177e4SLinus Torvalds * that we obtain it on our own. This function will *not* return until 10971da177e4SLinus Torvalds * the command either times out, or it completes. 1098dc8875e1SRandy Dunlap */ 10991da177e4SLinus Torvalds static int scsi_request_sense(struct scsi_cmnd *scmd) 11001da177e4SLinus Torvalds { 11010816c925SMartin K. Petersen return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0); 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 11042451079bSJames Bottomley static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn) 11052451079bSJames Bottomley { 110657292b58SChristoph Hellwig if (!blk_rq_is_passthrough(scmd->request)) { 11072451079bSJames Bottomley struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); 11082451079bSJames Bottomley if (sdrv->eh_action) 11092451079bSJames Bottomley rtn = sdrv->eh_action(scmd, rtn); 11102451079bSJames Bottomley } 11112451079bSJames Bottomley return rtn; 11122451079bSJames Bottomley } 11132451079bSJames Bottomley 11141da177e4SLinus Torvalds /** 11151da177e4SLinus Torvalds * scsi_eh_finish_cmd - Handle a cmd that eh is finished with. 11161da177e4SLinus Torvalds * @scmd: Original SCSI cmd that eh has finished. 11171da177e4SLinus Torvalds * @done_q: Queue for processed commands. 11181da177e4SLinus Torvalds * 11191da177e4SLinus Torvalds * Notes: 11201da177e4SLinus Torvalds * We don't want to use the normal command completion while we are are 11211da177e4SLinus Torvalds * still handling errors - it may cause other commands to be queued, 1122eb44820cSRob Landley * and that would disturb what we are doing. Thus we really want to 11231da177e4SLinus Torvalds * keep a list of pending commands for final completion, and once we 11241da177e4SLinus Torvalds * are ready to leave error handling we handle completion for real. 1125dc8875e1SRandy Dunlap */ 1126041c5fc3STejun Heo void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q) 11271da177e4SLinus Torvalds { 11281da177e4SLinus Torvalds list_move_tail(&scmd->eh_entry, done_q); 11291da177e4SLinus Torvalds } 1130041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_finish_cmd); 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds /** 11331da177e4SLinus Torvalds * scsi_eh_get_sense - Get device sense data. 11341da177e4SLinus Torvalds * @work_q: Queue of commands to process. 1135eb44820cSRob Landley * @done_q: Queue of processed commands. 11361da177e4SLinus Torvalds * 11371da177e4SLinus Torvalds * Description: 11381da177e4SLinus Torvalds * See if we need to request sense information. if so, then get it 11391da177e4SLinus Torvalds * now, so we have a better idea of what to do. 11401da177e4SLinus Torvalds * 11411da177e4SLinus Torvalds * Notes: 11421da177e4SLinus Torvalds * This has the unfortunate side effect that if a shost adapter does 1143eb44820cSRob Landley * not automatically request sense information, we end up shutting 11441da177e4SLinus Torvalds * it down before we request it. 11451da177e4SLinus Torvalds * 11461da177e4SLinus Torvalds * All drivers should request sense information internally these days, 11471da177e4SLinus Torvalds * so for now all I have to say is tough noogies if you end up in here. 11481da177e4SLinus Torvalds * 11491da177e4SLinus Torvalds * XXX: Long term this code should go away, but that needs an audit of 11501da177e4SLinus Torvalds * all LLDDs first. 1151dc8875e1SRandy Dunlap */ 1152dca84e46SDarrick J. Wong int scsi_eh_get_sense(struct list_head *work_q, 11531da177e4SLinus Torvalds struct list_head *done_q) 11541da177e4SLinus Torvalds { 1155937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *next; 1156b4562022SHannes Reinecke struct Scsi_Host *shost; 11571da177e4SLinus Torvalds int rtn; 11581da177e4SLinus Torvalds 1159709c75b5Sjiang.biao2@zte.com.cn /* 1160709c75b5Sjiang.biao2@zte.com.cn * If SCSI_EH_ABORT_SCHEDULED has been set, it is timeout IO, 1161709c75b5Sjiang.biao2@zte.com.cn * should not get sense. 1162709c75b5Sjiang.biao2@zte.com.cn */ 1163937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1164a0658632SHannes Reinecke if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) || 11651da177e4SLinus Torvalds SCSI_SENSE_VALID(scmd)) 11661da177e4SLinus Torvalds continue; 11671da177e4SLinus Torvalds 1168b4562022SHannes Reinecke shost = scmd->device->host; 1169b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(shost)) { 1170b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1171a222b1e2SHannes Reinecke scmd_printk(KERN_INFO, scmd, 1172a222b1e2SHannes Reinecke "%s: skip request sense, past eh deadline\n", 1173a222b1e2SHannes Reinecke current->comm)); 1174b4562022SHannes Reinecke break; 1175b4562022SHannes Reinecke } 1176d555a2abSJames Bottomley if (status_byte(scmd->result) != CHECK_CONDITION) 1177d555a2abSJames Bottomley /* 1178d555a2abSJames Bottomley * don't request sense if there's no check condition 1179d555a2abSJames Bottomley * status because the error we're processing isn't one 1180d555a2abSJames Bottomley * that has a sense code (and some devices get 1181d555a2abSJames Bottomley * confused by sense requests out of the blue) 1182d555a2abSJames Bottomley */ 1183d555a2abSJames Bottomley continue; 1184d555a2abSJames Bottomley 11853bf743e7SJeff Garzik SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, 11863bf743e7SJeff Garzik "%s: requesting sense\n", 11873bf743e7SJeff Garzik current->comm)); 11881da177e4SLinus Torvalds rtn = scsi_request_sense(scmd); 11891da177e4SLinus Torvalds if (rtn != SUCCESS) 11901da177e4SLinus Torvalds continue; 11911da177e4SLinus Torvalds 119291921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 1193470613b4SHannes Reinecke "sense requested, result %x\n", scmd->result)); 1194d811b848SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense(scmd)); 11951da177e4SLinus Torvalds 11961da177e4SLinus Torvalds rtn = scsi_decide_disposition(scmd); 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds /* 11991da177e4SLinus Torvalds * if the result was normal, then just pass it along to the 12001da177e4SLinus Torvalds * upper level. 12011da177e4SLinus Torvalds */ 12021da177e4SLinus Torvalds if (rtn == SUCCESS) 12031da177e4SLinus Torvalds /* we don't want this command reissued, just 12041da177e4SLinus Torvalds * finished with the sense data, so set 12051da177e4SLinus Torvalds * retries to the max allowed to ensure it 12061da177e4SLinus Torvalds * won't get reissued */ 12071da177e4SLinus Torvalds scmd->retries = scmd->allowed; 12081da177e4SLinus Torvalds else if (rtn != NEEDS_RETRY) 12091da177e4SLinus Torvalds continue; 12101da177e4SLinus Torvalds 12111da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, done_q); 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds return list_empty(work_q); 12151da177e4SLinus Torvalds } 1216dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_get_sense); 12171da177e4SLinus Torvalds 12181da177e4SLinus Torvalds /** 12191da177e4SLinus Torvalds * scsi_eh_tur - Send TUR to device. 1220eb44820cSRob Landley * @scmd: &scsi_cmnd to send TUR 12211da177e4SLinus Torvalds * 12221da177e4SLinus Torvalds * Return value: 12231da177e4SLinus Torvalds * 0 - Device is ready. 1 - Device NOT ready. 1224dc8875e1SRandy Dunlap */ 12251da177e4SLinus Torvalds static int scsi_eh_tur(struct scsi_cmnd *scmd) 12261da177e4SLinus Torvalds { 12271da177e4SLinus Torvalds static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; 12281da177e4SLinus Torvalds int retry_cnt = 1, rtn; 12291da177e4SLinus Torvalds 12301da177e4SLinus Torvalds retry_tur: 12310816c925SMartin K. Petersen rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, 12320816c925SMartin K. Petersen scmd->device->eh_timeout, 0); 12331da177e4SLinus Torvalds 123491921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, 1235470613b4SHannes Reinecke "%s return: %x\n", __func__, rtn)); 1236631c228cSChristoph Hellwig 1237631c228cSChristoph Hellwig switch (rtn) { 1238631c228cSChristoph Hellwig case NEEDS_RETRY: 12391da177e4SLinus Torvalds if (retry_cnt--) 12401da177e4SLinus Torvalds goto retry_tur; 1241631c228cSChristoph Hellwig /*FALLTHRU*/ 1242631c228cSChristoph Hellwig case SUCCESS: 1243e47373ecSAlan Stern return 0; 1244631c228cSChristoph Hellwig default: 12451da177e4SLinus Torvalds return 1; 12461da177e4SLinus Torvalds } 1247631c228cSChristoph Hellwig } 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds /** 12503eef6257SDavid Jeffery * scsi_eh_test_devices - check if devices are responding from error recovery. 12513eef6257SDavid Jeffery * @cmd_list: scsi commands in error recovery. 12523eef6257SDavid Jeffery * @work_q: queue for commands which still need more error recovery 12533eef6257SDavid Jeffery * @done_q: queue for commands which are finished 12543eef6257SDavid Jeffery * @try_stu: boolean on if a STU command should be tried in addition to TUR. 12553eef6257SDavid Jeffery * 12563eef6257SDavid Jeffery * Decription: 12573eef6257SDavid Jeffery * Tests if devices are in a working state. Commands to devices now in 12583eef6257SDavid Jeffery * a working state are sent to the done_q while commands to devices which 12593eef6257SDavid Jeffery * are still failing to respond are returned to the work_q for more 12603eef6257SDavid Jeffery * processing. 12613eef6257SDavid Jeffery **/ 12623eef6257SDavid Jeffery static int scsi_eh_test_devices(struct list_head *cmd_list, 12633eef6257SDavid Jeffery struct list_head *work_q, 12643eef6257SDavid Jeffery struct list_head *done_q, int try_stu) 12653eef6257SDavid Jeffery { 12663eef6257SDavid Jeffery struct scsi_cmnd *scmd, *next; 12673eef6257SDavid Jeffery struct scsi_device *sdev; 12683eef6257SDavid Jeffery int finish_cmds; 12693eef6257SDavid Jeffery 12703eef6257SDavid Jeffery while (!list_empty(cmd_list)) { 12713eef6257SDavid Jeffery scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); 12723eef6257SDavid Jeffery sdev = scmd->device; 12733eef6257SDavid Jeffery 1274b4562022SHannes Reinecke if (!try_stu) { 1275b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(sdev->host)) { 1276b4562022SHannes Reinecke /* Push items back onto work_q */ 1277b4562022SHannes Reinecke list_splice_init(cmd_list, work_q); 1278b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1279a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1280a222b1e2SHannes Reinecke "%s: skip test device, past eh deadline", 1281a222b1e2SHannes Reinecke current->comm)); 1282b4562022SHannes Reinecke break; 1283b4562022SHannes Reinecke } 1284b4562022SHannes Reinecke } 1285b4562022SHannes Reinecke 12863eef6257SDavid Jeffery finish_cmds = !scsi_device_online(scmd->device) || 12873eef6257SDavid Jeffery (try_stu && !scsi_eh_try_stu(scmd) && 12883eef6257SDavid Jeffery !scsi_eh_tur(scmd)) || 12893eef6257SDavid Jeffery !scsi_eh_tur(scmd); 12903eef6257SDavid Jeffery 12913eef6257SDavid Jeffery list_for_each_entry_safe(scmd, next, cmd_list, eh_entry) 12923eef6257SDavid Jeffery if (scmd->device == sdev) { 12932451079bSJames Bottomley if (finish_cmds && 12942451079bSJames Bottomley (try_stu || 12952451079bSJames Bottomley scsi_eh_action(scmd, SUCCESS) == SUCCESS)) 12963eef6257SDavid Jeffery scsi_eh_finish_cmd(scmd, done_q); 12973eef6257SDavid Jeffery else 12983eef6257SDavid Jeffery list_move_tail(&scmd->eh_entry, work_q); 12993eef6257SDavid Jeffery } 13003eef6257SDavid Jeffery } 13013eef6257SDavid Jeffery return list_empty(work_q); 13023eef6257SDavid Jeffery } 13033eef6257SDavid Jeffery 13041da177e4SLinus Torvalds /** 13051da177e4SLinus Torvalds * scsi_eh_try_stu - Send START_UNIT to device. 1306eb44820cSRob Landley * @scmd: &scsi_cmnd to send START_UNIT 13071da177e4SLinus Torvalds * 13081da177e4SLinus Torvalds * Return value: 13091da177e4SLinus Torvalds * 0 - Device is ready. 1 - Device NOT ready. 1310dc8875e1SRandy Dunlap */ 13111da177e4SLinus Torvalds static int scsi_eh_try_stu(struct scsi_cmnd *scmd) 13121da177e4SLinus Torvalds { 13131da177e4SLinus Torvalds static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0}; 13141da177e4SLinus Torvalds 1315631c228cSChristoph Hellwig if (scmd->device->allow_restart) { 1316ed773e66SBrian King int i, rtn = NEEDS_RETRY; 13171da177e4SLinus Torvalds 1318ed773e66SBrian King for (i = 0; rtn == NEEDS_RETRY && i < 2; i++) 13199728c081SJames Bottomley rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0); 1320ed773e66SBrian King 13211da177e4SLinus Torvalds if (rtn == SUCCESS) 13221da177e4SLinus Torvalds return 0; 1323631c228cSChristoph Hellwig } 1324631c228cSChristoph Hellwig 13251da177e4SLinus Torvalds return 1; 13261da177e4SLinus Torvalds } 13271da177e4SLinus Torvalds 13281da177e4SLinus Torvalds /** 13291da177e4SLinus Torvalds * scsi_eh_stu - send START_UNIT if needed 1330eb44820cSRob Landley * @shost: &scsi host being recovered. 1331eb44820cSRob Landley * @work_q: &list_head for pending commands. 1332eb44820cSRob Landley * @done_q: &list_head for processed commands. 13331da177e4SLinus Torvalds * 13341da177e4SLinus Torvalds * Notes: 13351da177e4SLinus Torvalds * If commands are failing due to not ready, initializing command required, 13361da177e4SLinus Torvalds * try revalidating the device, which will end up sending a start unit. 1337dc8875e1SRandy Dunlap */ 13381da177e4SLinus Torvalds static int scsi_eh_stu(struct Scsi_Host *shost, 13391da177e4SLinus Torvalds struct list_head *work_q, 13401da177e4SLinus Torvalds struct list_head *done_q) 13411da177e4SLinus Torvalds { 1342937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *stu_scmd, *next; 13431da177e4SLinus Torvalds struct scsi_device *sdev; 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds shost_for_each_device(sdev, shost) { 1346b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(shost)) { 1347b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1348a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1349a222b1e2SHannes Reinecke "%s: skip START_UNIT, past eh deadline\n", 1350a222b1e2SHannes Reinecke current->comm)); 1351b4562022SHannes Reinecke break; 1352b4562022SHannes Reinecke } 13531da177e4SLinus Torvalds stu_scmd = NULL; 13541da177e4SLinus Torvalds list_for_each_entry(scmd, work_q, eh_entry) 13551da177e4SLinus Torvalds if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && 13561da177e4SLinus Torvalds scsi_check_sense(scmd) == FAILED ) { 13571da177e4SLinus Torvalds stu_scmd = scmd; 13581da177e4SLinus Torvalds break; 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds 13611da177e4SLinus Torvalds if (!stu_scmd) 13621da177e4SLinus Torvalds continue; 13631da177e4SLinus Torvalds 136491921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1365a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1366a222b1e2SHannes Reinecke "%s: Sending START_UNIT\n", 1367a222b1e2SHannes Reinecke current->comm)); 13681da177e4SLinus Torvalds 13691da177e4SLinus Torvalds if (!scsi_eh_try_stu(stu_scmd)) { 13701da177e4SLinus Torvalds if (!scsi_device_online(sdev) || 13711da177e4SLinus Torvalds !scsi_eh_tur(stu_scmd)) { 1372937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, 1373937abeaaSChristoph Hellwig work_q, eh_entry) { 13742451079bSJames Bottomley if (scmd->device == sdev && 13752451079bSJames Bottomley scsi_eh_action(scmd, SUCCESS) == SUCCESS) 13761da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, done_q); 13771da177e4SLinus Torvalds } 13781da177e4SLinus Torvalds } 13791da177e4SLinus Torvalds } else { 13801da177e4SLinus Torvalds SCSI_LOG_ERROR_RECOVERY(3, 1381a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1382a222b1e2SHannes Reinecke "%s: START_UNIT failed\n", 1383a222b1e2SHannes Reinecke current->comm)); 13841da177e4SLinus Torvalds } 13851da177e4SLinus Torvalds } 13861da177e4SLinus Torvalds 13871da177e4SLinus Torvalds return list_empty(work_q); 13881da177e4SLinus Torvalds } 13891da177e4SLinus Torvalds 13901da177e4SLinus Torvalds 13911da177e4SLinus Torvalds /** 13921da177e4SLinus Torvalds * scsi_eh_bus_device_reset - send bdr if needed 13931da177e4SLinus Torvalds * @shost: scsi host being recovered. 1394eb44820cSRob Landley * @work_q: &list_head for pending commands. 1395eb44820cSRob Landley * @done_q: &list_head for processed commands. 13961da177e4SLinus Torvalds * 13971da177e4SLinus Torvalds * Notes: 1398eb44820cSRob Landley * Try a bus device reset. Still, look to see whether we have multiple 13991da177e4SLinus Torvalds * devices that are jammed or not - if we have multiple devices, it 14001da177e4SLinus Torvalds * makes no sense to try bus_device_reset - we really would need to try 14011da177e4SLinus Torvalds * a bus_reset instead. 1402dc8875e1SRandy Dunlap */ 14031da177e4SLinus Torvalds static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, 14041da177e4SLinus Torvalds struct list_head *work_q, 14051da177e4SLinus Torvalds struct list_head *done_q) 14061da177e4SLinus Torvalds { 1407937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *bdr_scmd, *next; 14081da177e4SLinus Torvalds struct scsi_device *sdev; 14091da177e4SLinus Torvalds int rtn; 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds shost_for_each_device(sdev, shost) { 1412b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(shost)) { 1413b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1414a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1415a222b1e2SHannes Reinecke "%s: skip BDR, past eh deadline\n", 1416a222b1e2SHannes Reinecke current->comm)); 1417b4562022SHannes Reinecke break; 1418b4562022SHannes Reinecke } 14191da177e4SLinus Torvalds bdr_scmd = NULL; 14201da177e4SLinus Torvalds list_for_each_entry(scmd, work_q, eh_entry) 14211da177e4SLinus Torvalds if (scmd->device == sdev) { 14221da177e4SLinus Torvalds bdr_scmd = scmd; 14231da177e4SLinus Torvalds break; 14241da177e4SLinus Torvalds } 14251da177e4SLinus Torvalds 14261da177e4SLinus Torvalds if (!bdr_scmd) 14271da177e4SLinus Torvalds continue; 14281da177e4SLinus Torvalds 142991921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1430a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1431a222b1e2SHannes Reinecke "%s: Sending BDR\n", current->comm)); 14321da177e4SLinus Torvalds rtn = scsi_try_bus_device_reset(bdr_scmd); 14332f2eb587SChristof Schmitt if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { 14341da177e4SLinus Torvalds if (!scsi_device_online(sdev) || 14352f2eb587SChristof Schmitt rtn == FAST_IO_FAIL || 14361da177e4SLinus Torvalds !scsi_eh_tur(bdr_scmd)) { 1437937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, 1438937abeaaSChristoph Hellwig work_q, eh_entry) { 14392451079bSJames Bottomley if (scmd->device == sdev && 14402451079bSJames Bottomley scsi_eh_action(scmd, rtn) != FAILED) 14411da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, 14421da177e4SLinus Torvalds done_q); 14431da177e4SLinus Torvalds } 14441da177e4SLinus Torvalds } 14451da177e4SLinus Torvalds } else { 144691921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1447a222b1e2SHannes Reinecke sdev_printk(KERN_INFO, sdev, 1448a222b1e2SHannes Reinecke "%s: BDR failed\n", current->comm)); 14491da177e4SLinus Torvalds } 14501da177e4SLinus Torvalds } 14511da177e4SLinus Torvalds 14521da177e4SLinus Torvalds return list_empty(work_q); 14531da177e4SLinus Torvalds } 14541da177e4SLinus Torvalds 14551da177e4SLinus Torvalds /** 145630bd7df8SMike Christie * scsi_eh_target_reset - send target reset if needed 145730bd7df8SMike Christie * @shost: scsi host being recovered. 145830bd7df8SMike Christie * @work_q: &list_head for pending commands. 145930bd7df8SMike Christie * @done_q: &list_head for processed commands. 146030bd7df8SMike Christie * 146130bd7df8SMike Christie * Notes: 146230bd7df8SMike Christie * Try a target reset. 146330bd7df8SMike Christie */ 146430bd7df8SMike Christie static int scsi_eh_target_reset(struct Scsi_Host *shost, 146530bd7df8SMike Christie struct list_head *work_q, 146630bd7df8SMike Christie struct list_head *done_q) 146730bd7df8SMike Christie { 146898db5195SJames Bottomley LIST_HEAD(tmp_list); 14693eef6257SDavid Jeffery LIST_HEAD(check_list); 147030bd7df8SMike Christie 147198db5195SJames Bottomley list_splice_init(work_q, &tmp_list); 147298db5195SJames Bottomley 147398db5195SJames Bottomley while (!list_empty(&tmp_list)) { 147498db5195SJames Bottomley struct scsi_cmnd *next, *scmd; 147598db5195SJames Bottomley int rtn; 147698db5195SJames Bottomley unsigned int id; 1477b4562022SHannes Reinecke 1478b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(shost)) { 1479b4562022SHannes Reinecke /* push back on work queue for further processing */ 1480b4562022SHannes Reinecke list_splice_init(&check_list, work_q); 1481b4562022SHannes Reinecke list_splice_init(&tmp_list, work_q); 1482b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1483b4562022SHannes Reinecke shost_printk(KERN_INFO, shost, 1484a222b1e2SHannes Reinecke "%s: Skip target reset, past eh deadline\n", 1485a222b1e2SHannes Reinecke current->comm)); 1486b4562022SHannes Reinecke return list_empty(work_q); 1487b4562022SHannes Reinecke } 148898db5195SJames Bottomley 148998db5195SJames Bottomley scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); 149098db5195SJames Bottomley id = scmd_id(scmd); 149130bd7df8SMike Christie 149291921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 149391921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 149491921e01SHannes Reinecke "%s: Sending target reset to target %d\n", 149530bd7df8SMike Christie current->comm, id)); 149698db5195SJames Bottomley rtn = scsi_try_target_reset(scmd); 149798db5195SJames Bottomley if (rtn != SUCCESS && rtn != FAST_IO_FAIL) 149891921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 149991921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 150091921e01SHannes Reinecke "%s: Target reset failed" 150191921e01SHannes Reinecke " target: %d\n", 150230bd7df8SMike Christie current->comm, id)); 150398db5195SJames Bottomley list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) { 150498db5195SJames Bottomley if (scmd_id(scmd) != id) 150598db5195SJames Bottomley continue; 150698db5195SJames Bottomley 15073eef6257SDavid Jeffery if (rtn == SUCCESS) 15083eef6257SDavid Jeffery list_move_tail(&scmd->eh_entry, &check_list); 15093eef6257SDavid Jeffery else if (rtn == FAST_IO_FAIL) 151098db5195SJames Bottomley scsi_eh_finish_cmd(scmd, done_q); 151198db5195SJames Bottomley else 151298db5195SJames Bottomley /* push back on work queue for further processing */ 151398db5195SJames Bottomley list_move(&scmd->eh_entry, work_q); 151498db5195SJames Bottomley } 151598db5195SJames Bottomley } 151630bd7df8SMike Christie 15173eef6257SDavid Jeffery return scsi_eh_test_devices(&check_list, work_q, done_q, 0); 151830bd7df8SMike Christie } 151930bd7df8SMike Christie 152030bd7df8SMike Christie /** 15211da177e4SLinus Torvalds * scsi_eh_bus_reset - send a bus reset 1522eb44820cSRob Landley * @shost: &scsi host being recovered. 1523eb44820cSRob Landley * @work_q: &list_head for pending commands. 1524eb44820cSRob Landley * @done_q: &list_head for processed commands. 1525dc8875e1SRandy Dunlap */ 15261da177e4SLinus Torvalds static int scsi_eh_bus_reset(struct Scsi_Host *shost, 15271da177e4SLinus Torvalds struct list_head *work_q, 15281da177e4SLinus Torvalds struct list_head *done_q) 15291da177e4SLinus Torvalds { 1530937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *chan_scmd, *next; 15313eef6257SDavid Jeffery LIST_HEAD(check_list); 15321da177e4SLinus Torvalds unsigned int channel; 15331da177e4SLinus Torvalds int rtn; 15341da177e4SLinus Torvalds 15351da177e4SLinus Torvalds /* 15361da177e4SLinus Torvalds * we really want to loop over the various channels, and do this on 15371da177e4SLinus Torvalds * a channel by channel basis. we should also check to see if any 15381da177e4SLinus Torvalds * of the failed commands are on soft_reset devices, and if so, skip 15391da177e4SLinus Torvalds * the reset. 15401da177e4SLinus Torvalds */ 15411da177e4SLinus Torvalds 15421da177e4SLinus Torvalds for (channel = 0; channel <= shost->max_channel; channel++) { 1543b4562022SHannes Reinecke if (scsi_host_eh_past_deadline(shost)) { 1544b4562022SHannes Reinecke list_splice_init(&check_list, work_q); 1545b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 1546b4562022SHannes Reinecke shost_printk(KERN_INFO, shost, 1547a222b1e2SHannes Reinecke "%s: skip BRST, past eh deadline\n", 1548a222b1e2SHannes Reinecke current->comm)); 1549b4562022SHannes Reinecke return list_empty(work_q); 1550b4562022SHannes Reinecke } 1551b4562022SHannes Reinecke 15521da177e4SLinus Torvalds chan_scmd = NULL; 15531da177e4SLinus Torvalds list_for_each_entry(scmd, work_q, eh_entry) { 1554422c0d61SJeff Garzik if (channel == scmd_channel(scmd)) { 15551da177e4SLinus Torvalds chan_scmd = scmd; 15561da177e4SLinus Torvalds break; 15571da177e4SLinus Torvalds /* 15581da177e4SLinus Torvalds * FIXME add back in some support for 15591da177e4SLinus Torvalds * soft_reset devices. 15601da177e4SLinus Torvalds */ 15611da177e4SLinus Torvalds } 15621da177e4SLinus Torvalds } 15631da177e4SLinus Torvalds 15641da177e4SLinus Torvalds if (!chan_scmd) 15651da177e4SLinus Torvalds continue; 156691921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 156791921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 156891921e01SHannes Reinecke "%s: Sending BRST chan: %d\n", 156991921e01SHannes Reinecke current->comm, channel)); 15701da177e4SLinus Torvalds rtn = scsi_try_bus_reset(chan_scmd); 15712f2eb587SChristof Schmitt if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { 1572937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 15733eef6257SDavid Jeffery if (channel == scmd_channel(scmd)) { 15743eef6257SDavid Jeffery if (rtn == FAST_IO_FAIL) 15751da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, 15761da177e4SLinus Torvalds done_q); 15773eef6257SDavid Jeffery else 15783eef6257SDavid Jeffery list_move_tail(&scmd->eh_entry, 15793eef6257SDavid Jeffery &check_list); 15803eef6257SDavid Jeffery } 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds } else { 158391921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 158491921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 158591921e01SHannes Reinecke "%s: BRST failed chan: %d\n", 158691921e01SHannes Reinecke current->comm, channel)); 15871da177e4SLinus Torvalds } 15881da177e4SLinus Torvalds } 15893eef6257SDavid Jeffery return scsi_eh_test_devices(&check_list, work_q, done_q, 0); 15901da177e4SLinus Torvalds } 15911da177e4SLinus Torvalds 15921da177e4SLinus Torvalds /** 15931da177e4SLinus Torvalds * scsi_eh_host_reset - send a host reset 159474cf298fSRandy Dunlap * @shost: host to be reset. 159574cf298fSRandy Dunlap * @work_q: &list_head for pending commands. 159674cf298fSRandy Dunlap * @done_q: &list_head for processed commands. 1597dc8875e1SRandy Dunlap */ 159891921e01SHannes Reinecke static int scsi_eh_host_reset(struct Scsi_Host *shost, 159991921e01SHannes Reinecke struct list_head *work_q, 16001da177e4SLinus Torvalds struct list_head *done_q) 16011da177e4SLinus Torvalds { 1602937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *next; 16033eef6257SDavid Jeffery LIST_HEAD(check_list); 16041da177e4SLinus Torvalds int rtn; 16051da177e4SLinus Torvalds 16061da177e4SLinus Torvalds if (!list_empty(work_q)) { 16071da177e4SLinus Torvalds scmd = list_entry(work_q->next, 16081da177e4SLinus Torvalds struct scsi_cmnd, eh_entry); 16091da177e4SLinus Torvalds 161091921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 161191921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 161291921e01SHannes Reinecke "%s: Sending HRST\n", 161391921e01SHannes Reinecke current->comm)); 16141da177e4SLinus Torvalds 16151da177e4SLinus Torvalds rtn = scsi_try_host_reset(scmd); 16163eef6257SDavid Jeffery if (rtn == SUCCESS) { 16173eef6257SDavid Jeffery list_splice_init(work_q, &check_list); 16183eef6257SDavid Jeffery } else if (rtn == FAST_IO_FAIL) { 1619937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 16201da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, done_q); 16211da177e4SLinus Torvalds } 16221da177e4SLinus Torvalds } else { 162391921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 162491921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 162591921e01SHannes Reinecke "%s: HRST failed\n", 16261da177e4SLinus Torvalds current->comm)); 16271da177e4SLinus Torvalds } 16281da177e4SLinus Torvalds } 16293eef6257SDavid Jeffery return scsi_eh_test_devices(&check_list, work_q, done_q, 1); 16301da177e4SLinus Torvalds } 16311da177e4SLinus Torvalds 16321da177e4SLinus Torvalds /** 16331da177e4SLinus Torvalds * scsi_eh_offline_sdevs - offline scsi devices that fail to recover 163474cf298fSRandy Dunlap * @work_q: &list_head for pending commands. 163574cf298fSRandy Dunlap * @done_q: &list_head for processed commands. 1636dc8875e1SRandy Dunlap */ 16371da177e4SLinus Torvalds static void scsi_eh_offline_sdevs(struct list_head *work_q, 16381da177e4SLinus Torvalds struct list_head *done_q) 16391da177e4SLinus Torvalds { 1640937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *next; 16410db6ca8aSBart Van Assche struct scsi_device *sdev; 16421da177e4SLinus Torvalds 1643937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 164431765d7dSMatthew Wilcox sdev_printk(KERN_INFO, scmd->device, "Device offlined - " 164531765d7dSMatthew Wilcox "not ready after error recovery\n"); 16460db6ca8aSBart Van Assche sdev = scmd->device; 16470db6ca8aSBart Van Assche 16480db6ca8aSBart Van Assche mutex_lock(&sdev->state_mutex); 16490db6ca8aSBart Van Assche scsi_device_set_state(sdev, SDEV_OFFLINE); 16500db6ca8aSBart Van Assche mutex_unlock(&sdev->state_mutex); 16510db6ca8aSBart Van Assche 16521da177e4SLinus Torvalds scsi_eh_finish_cmd(scmd, done_q); 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds return; 16551da177e4SLinus Torvalds } 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds /** 1658e494f6a7SHannes Reinecke * scsi_noretry_cmd - determine if command should be failed fast 16594a27446fSMike Christie * @scmd: SCSI cmd to examine. 16604a27446fSMike Christie */ 16614a27446fSMike Christie int scsi_noretry_cmd(struct scsi_cmnd *scmd) 16624a27446fSMike Christie { 16634a27446fSMike Christie switch (host_byte(scmd->result)) { 16644a27446fSMike Christie case DID_OK: 16654a27446fSMike Christie break; 1666e494f6a7SHannes Reinecke case DID_TIME_OUT: 1667e494f6a7SHannes Reinecke goto check_type; 16684a27446fSMike Christie case DID_BUS_BUSY: 166933659ebbSChristoph Hellwig return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT); 16704a27446fSMike Christie case DID_PARITY: 167133659ebbSChristoph Hellwig return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); 16724a27446fSMike Christie case DID_ERROR: 16734a27446fSMike Christie if (msg_byte(scmd->result) == COMMAND_COMPLETE && 16744a27446fSMike Christie status_byte(scmd->result) == RESERVATION_CONFLICT) 16754a27446fSMike Christie return 0; 16764a27446fSMike Christie /* fall through */ 16774a27446fSMike Christie case DID_SOFT_ERROR: 167833659ebbSChristoph Hellwig return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER); 16794a27446fSMike Christie } 16804a27446fSMike Christie 1681e494f6a7SHannes Reinecke if (status_byte(scmd->result) != CHECK_CONDITION) 1682e494f6a7SHannes Reinecke return 0; 1683e494f6a7SHannes Reinecke 1684e494f6a7SHannes Reinecke check_type: 16854a27446fSMike Christie /* 1686e494f6a7SHannes Reinecke * assume caller has checked sense and determined 16874a27446fSMike Christie * the check condition was retryable. 16884a27446fSMike Christie */ 1689e96f6abeSFUJITA Tomonori if (scmd->request->cmd_flags & REQ_FAILFAST_DEV || 169057292b58SChristoph Hellwig blk_rq_is_passthrough(scmd->request)) 1691e96f6abeSFUJITA Tomonori return 1; 1692e494f6a7SHannes Reinecke else 16934a27446fSMike Christie return 0; 16944a27446fSMike Christie } 16954a27446fSMike Christie 16964a27446fSMike Christie /** 16971da177e4SLinus Torvalds * scsi_decide_disposition - Disposition a cmd on return from LLD. 16981da177e4SLinus Torvalds * @scmd: SCSI cmd to examine. 16991da177e4SLinus Torvalds * 17001da177e4SLinus Torvalds * Notes: 17011da177e4SLinus Torvalds * This is *only* called when we are examining the status after sending 17021da177e4SLinus Torvalds * out the actual data command. any commands that are queued for error 17031da177e4SLinus Torvalds * recovery (e.g. test_unit_ready) do *not* come through here. 17041da177e4SLinus Torvalds * 17051da177e4SLinus Torvalds * When this routine returns failed, it means the error handler thread 17061da177e4SLinus Torvalds * is woken. In cases where the error code indicates an error that 17071da177e4SLinus Torvalds * doesn't require the error handler read (i.e. we don't need to 17081da177e4SLinus Torvalds * abort/reset), this function should return SUCCESS. 1709dc8875e1SRandy Dunlap */ 17101da177e4SLinus Torvalds int scsi_decide_disposition(struct scsi_cmnd *scmd) 17111da177e4SLinus Torvalds { 17121da177e4SLinus Torvalds int rtn; 17131da177e4SLinus Torvalds 17141da177e4SLinus Torvalds /* 17151da177e4SLinus Torvalds * if the device is offline, then we clearly just pass the result back 17161da177e4SLinus Torvalds * up to the top level. 17171da177e4SLinus Torvalds */ 17181da177e4SLinus Torvalds if (!scsi_device_online(scmd->device)) { 171991921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd, 172091921e01SHannes Reinecke "%s: device offline - report as SUCCESS\n", __func__)); 17211da177e4SLinus Torvalds return SUCCESS; 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds 17241da177e4SLinus Torvalds /* 17251da177e4SLinus Torvalds * first check the host byte, to see if there is anything in there 17261da177e4SLinus Torvalds * that would indicate what we need to do. 17271da177e4SLinus Torvalds */ 17281da177e4SLinus Torvalds switch (host_byte(scmd->result)) { 17291da177e4SLinus Torvalds case DID_PASSTHROUGH: 17301da177e4SLinus Torvalds /* 17311da177e4SLinus Torvalds * no matter what, pass this through to the upper layer. 17321da177e4SLinus Torvalds * nuke this special code so that it looks like we are saying 17331da177e4SLinus Torvalds * did_ok. 17341da177e4SLinus Torvalds */ 17351da177e4SLinus Torvalds scmd->result &= 0xff00ffff; 17361da177e4SLinus Torvalds return SUCCESS; 17371da177e4SLinus Torvalds case DID_OK: 17381da177e4SLinus Torvalds /* 17391da177e4SLinus Torvalds * looks good. drop through, and check the next byte. 17401da177e4SLinus Torvalds */ 17411da177e4SLinus Torvalds break; 1742e494f6a7SHannes Reinecke case DID_ABORT: 1743e494f6a7SHannes Reinecke if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) { 17448922a908SUlrich Obergfell set_host_byte(scmd, DID_TIME_OUT); 1745e494f6a7SHannes Reinecke return SUCCESS; 1746e494f6a7SHannes Reinecke } 17473bf2ff67SBart Van Assche /* FALLTHROUGH */ 17481da177e4SLinus Torvalds case DID_NO_CONNECT: 17491da177e4SLinus Torvalds case DID_BAD_TARGET: 17501da177e4SLinus Torvalds /* 17511da177e4SLinus Torvalds * note - this means that we just report the status back 17521da177e4SLinus Torvalds * to the top level driver, not that we actually think 17531da177e4SLinus Torvalds * that it indicates SUCCESS. 17541da177e4SLinus Torvalds */ 17551da177e4SLinus Torvalds return SUCCESS; 1756*ad95028aSPetros Koutoupis case DID_SOFT_ERROR: 17571da177e4SLinus Torvalds /* 17581da177e4SLinus Torvalds * when the low level driver returns did_soft_error, 17591da177e4SLinus Torvalds * it is responsible for keeping an internal retry counter 17601da177e4SLinus Torvalds * in order to avoid endless loops (db) 17611da177e4SLinus Torvalds */ 17621da177e4SLinus Torvalds goto maybe_retry; 17631da177e4SLinus Torvalds case DID_IMM_RETRY: 17641da177e4SLinus Torvalds return NEEDS_RETRY; 17651da177e4SLinus Torvalds 1766bf341919S case DID_REQUEUE: 1767bf341919S return ADD_TO_MLQUEUE; 1768a4dfaa6fSMike Christie case DID_TRANSPORT_DISRUPTED: 1769a4dfaa6fSMike Christie /* 1770a4dfaa6fSMike Christie * LLD/transport was disrupted during processing of the IO. 1771a4dfaa6fSMike Christie * The transport class is now blocked/blocking, 1772a4dfaa6fSMike Christie * and the transport will decide what to do with the IO 1773939c2288SMike Christie * based on its timers and recovery capablilities if 1774939c2288SMike Christie * there are enough retries. 1775a4dfaa6fSMike Christie */ 1776939c2288SMike Christie goto maybe_retry; 1777a4dfaa6fSMike Christie case DID_TRANSPORT_FAILFAST: 1778a4dfaa6fSMike Christie /* 1779a4dfaa6fSMike Christie * The transport decided to failfast the IO (most likely 1780a4dfaa6fSMike Christie * the fast io fail tmo fired), so send IO directly upwards. 1781a4dfaa6fSMike Christie */ 1782a4dfaa6fSMike Christie return SUCCESS; 17831da177e4SLinus Torvalds case DID_ERROR: 17841da177e4SLinus Torvalds if (msg_byte(scmd->result) == COMMAND_COMPLETE && 17851da177e4SLinus Torvalds status_byte(scmd->result) == RESERVATION_CONFLICT) 17861da177e4SLinus Torvalds /* 17871da177e4SLinus Torvalds * execute reservation conflict processing code 17881da177e4SLinus Torvalds * lower down 17891da177e4SLinus Torvalds */ 17901da177e4SLinus Torvalds break; 17911da177e4SLinus Torvalds /* fallthrough */ 17921da177e4SLinus Torvalds case DID_BUS_BUSY: 17931da177e4SLinus Torvalds case DID_PARITY: 17941da177e4SLinus Torvalds goto maybe_retry; 17951da177e4SLinus Torvalds case DID_TIME_OUT: 17961da177e4SLinus Torvalds /* 17971da177e4SLinus Torvalds * when we scan the bus, we get timeout messages for 17981da177e4SLinus Torvalds * these commands if there is no device available. 17991da177e4SLinus Torvalds * other hosts report did_no_connect for the same thing. 18001da177e4SLinus Torvalds */ 18011da177e4SLinus Torvalds if ((scmd->cmnd[0] == TEST_UNIT_READY || 18021da177e4SLinus Torvalds scmd->cmnd[0] == INQUIRY)) { 18031da177e4SLinus Torvalds return SUCCESS; 18041da177e4SLinus Torvalds } else { 18051da177e4SLinus Torvalds return FAILED; 18061da177e4SLinus Torvalds } 18071da177e4SLinus Torvalds case DID_RESET: 18081da177e4SLinus Torvalds return SUCCESS; 18091da177e4SLinus Torvalds default: 18101da177e4SLinus Torvalds return FAILED; 18111da177e4SLinus Torvalds } 18121da177e4SLinus Torvalds 18131da177e4SLinus Torvalds /* 18141da177e4SLinus Torvalds * next, check the message byte. 18151da177e4SLinus Torvalds */ 18161da177e4SLinus Torvalds if (msg_byte(scmd->result) != COMMAND_COMPLETE) 18171da177e4SLinus Torvalds return FAILED; 18181da177e4SLinus Torvalds 18191da177e4SLinus Torvalds /* 18201da177e4SLinus Torvalds * check the status byte to see if this indicates anything special. 18211da177e4SLinus Torvalds */ 18221da177e4SLinus Torvalds switch (status_byte(scmd->result)) { 18231da177e4SLinus Torvalds case QUEUE_FULL: 182442a6a918SMike Christie scsi_handle_queue_full(scmd->device); 18251da177e4SLinus Torvalds /* 18261da177e4SLinus Torvalds * the case of trying to send too many commands to a 18271da177e4SLinus Torvalds * tagged queueing device. 18281da177e4SLinus Torvalds */ 18293bf2ff67SBart Van Assche /* FALLTHROUGH */ 18301da177e4SLinus Torvalds case BUSY: 18311da177e4SLinus Torvalds /* 18321da177e4SLinus Torvalds * device can't talk to us at the moment. Should only 18331da177e4SLinus Torvalds * occur (SAM-3) when the task queue is empty, so will cause 18341da177e4SLinus Torvalds * the empty queue handling to trigger a stall in the 18351da177e4SLinus Torvalds * device. 18361da177e4SLinus Torvalds */ 18371da177e4SLinus Torvalds return ADD_TO_MLQUEUE; 18381da177e4SLinus Torvalds case GOOD: 1839279afdfeSEwan D. Milne if (scmd->cmnd[0] == REPORT_LUNS) 1840279afdfeSEwan D. Milne scmd->device->sdev_target->expecting_lun_change = 0; 18414a84067dSVasu Dev scsi_handle_queue_ramp_up(scmd->device); 18423bf2ff67SBart Van Assche /* FALLTHROUGH */ 18431da177e4SLinus Torvalds case COMMAND_TERMINATED: 18441da177e4SLinus Torvalds return SUCCESS; 1845a9b589d9SVladislav Bolkhovitin case TASK_ABORTED: 1846a9b589d9SVladislav Bolkhovitin goto maybe_retry; 18471da177e4SLinus Torvalds case CHECK_CONDITION: 18481da177e4SLinus Torvalds rtn = scsi_check_sense(scmd); 18491da177e4SLinus Torvalds if (rtn == NEEDS_RETRY) 18501da177e4SLinus Torvalds goto maybe_retry; 18511da177e4SLinus Torvalds /* if rtn == FAILED, we have no sense information; 18521da177e4SLinus Torvalds * returning FAILED will wake the error handler thread 18531da177e4SLinus Torvalds * to collect the sense and redo the decide 18541da177e4SLinus Torvalds * disposition */ 18551da177e4SLinus Torvalds return rtn; 18561da177e4SLinus Torvalds case CONDITION_GOOD: 18571da177e4SLinus Torvalds case INTERMEDIATE_GOOD: 18581da177e4SLinus Torvalds case INTERMEDIATE_C_GOOD: 18591da177e4SLinus Torvalds case ACA_ACTIVE: 18601da177e4SLinus Torvalds /* 18611da177e4SLinus Torvalds * who knows? FIXME(eric) 18621da177e4SLinus Torvalds */ 18631da177e4SLinus Torvalds return SUCCESS; 18641da177e4SLinus Torvalds 18651da177e4SLinus Torvalds case RESERVATION_CONFLICT: 18669ccfc756SJames Bottomley sdev_printk(KERN_INFO, scmd->device, 18679ccfc756SJames Bottomley "reservation conflict\n"); 18682082ebc4SMoger, Babu set_host_byte(scmd, DID_NEXUS_FAILURE); 18691da177e4SLinus Torvalds return SUCCESS; /* causes immediate i/o error */ 18701da177e4SLinus Torvalds default: 18711da177e4SLinus Torvalds return FAILED; 18721da177e4SLinus Torvalds } 18731da177e4SLinus Torvalds return FAILED; 18741da177e4SLinus Torvalds 18751da177e4SLinus Torvalds maybe_retry: 18761da177e4SLinus Torvalds 18771da177e4SLinus Torvalds /* we requeue for retry because the error was retryable, and 18781da177e4SLinus Torvalds * the request was not marked fast fail. Note that above, 18791da177e4SLinus Torvalds * even if the request is marked fast fail, we still requeue 18801da177e4SLinus Torvalds * for queue congestion conditions (QUEUE_FULL or BUSY) */ 18818884efabSBrian King if ((++scmd->retries) <= scmd->allowed 18824a27446fSMike Christie && !scsi_noretry_cmd(scmd)) { 18831da177e4SLinus Torvalds return NEEDS_RETRY; 18841da177e4SLinus Torvalds } else { 18851da177e4SLinus Torvalds /* 18861da177e4SLinus Torvalds * no more retries - report this one back to upper level. 18871da177e4SLinus Torvalds */ 18881da177e4SLinus Torvalds return SUCCESS; 18891da177e4SLinus Torvalds } 18901da177e4SLinus Torvalds } 18911da177e4SLinus Torvalds 18922a842acaSChristoph Hellwig static void eh_lock_door_done(struct request *req, blk_status_t status) 1893f078727bSFUJITA Tomonori { 1894f078727bSFUJITA Tomonori __blk_put_request(req->q, req); 1895f078727bSFUJITA Tomonori } 1896f078727bSFUJITA Tomonori 18971da177e4SLinus Torvalds /** 18981da177e4SLinus Torvalds * scsi_eh_lock_door - Prevent medium removal for the specified device 18991da177e4SLinus Torvalds * @sdev: SCSI device to prevent medium removal 19001da177e4SLinus Torvalds * 19011da177e4SLinus Torvalds * Locking: 190291bc31fbSJames Bottomley * We must be called from process context. 19031da177e4SLinus Torvalds * 19041da177e4SLinus Torvalds * Notes: 19051da177e4SLinus Torvalds * We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the 19061da177e4SLinus Torvalds * head of the devices request queue, and continue. 1907dc8875e1SRandy Dunlap */ 19081da177e4SLinus Torvalds static void scsi_eh_lock_door(struct scsi_device *sdev) 19091da177e4SLinus Torvalds { 1910f078727bSFUJITA Tomonori struct request *req; 191182ed4db4SChristoph Hellwig struct scsi_request *rq; 19121da177e4SLinus Torvalds 191391bc31fbSJames Bottomley /* 191471baba4bSMel Gorman * blk_get_request with GFP_KERNEL (__GFP_RECLAIM) sleeps until a 191591bc31fbSJames Bottomley * request becomes available 191691bc31fbSJames Bottomley */ 1917aebf526bSChristoph Hellwig req = blk_get_request(sdev->request_queue, REQ_OP_SCSI_IN, GFP_KERNEL); 1918a492f075SJoe Lawrence if (IS_ERR(req)) 1919eb571eeaSJoe Lawrence return; 192082ed4db4SChristoph Hellwig rq = scsi_req(req); 19211da177e4SLinus Torvalds 192282ed4db4SChristoph Hellwig rq->cmd[0] = ALLOW_MEDIUM_REMOVAL; 192382ed4db4SChristoph Hellwig rq->cmd[1] = 0; 192482ed4db4SChristoph Hellwig rq->cmd[2] = 0; 192582ed4db4SChristoph Hellwig rq->cmd[3] = 0; 192682ed4db4SChristoph Hellwig rq->cmd[4] = SCSI_REMOVAL_PREVENT; 192782ed4db4SChristoph Hellwig rq->cmd[5] = 0; 192882ed4db4SChristoph Hellwig rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); 1929f078727bSFUJITA Tomonori 1930e8064021SChristoph Hellwig req->rq_flags |= RQF_QUIET; 1931f078727bSFUJITA Tomonori req->timeout = 10 * HZ; 193264c7f1d1SChristoph Hellwig rq->retries = 5; 1933f078727bSFUJITA Tomonori 1934f078727bSFUJITA Tomonori blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done); 19351da177e4SLinus Torvalds } 19361da177e4SLinus Torvalds 19371da177e4SLinus Torvalds /** 19381da177e4SLinus Torvalds * scsi_restart_operations - restart io operations to the specified host. 19391da177e4SLinus Torvalds * @shost: Host we are restarting. 19401da177e4SLinus Torvalds * 19411da177e4SLinus Torvalds * Notes: 19421da177e4SLinus Torvalds * When we entered the error handler, we blocked all further i/o to 19431da177e4SLinus Torvalds * this device. we need to 'reverse' this process. 1944dc8875e1SRandy Dunlap */ 19451da177e4SLinus Torvalds static void scsi_restart_operations(struct Scsi_Host *shost) 19461da177e4SLinus Torvalds { 19471da177e4SLinus Torvalds struct scsi_device *sdev; 1948939647eeSJames Bottomley unsigned long flags; 19491da177e4SLinus Torvalds 19501da177e4SLinus Torvalds /* 19511da177e4SLinus Torvalds * If the door was locked, we need to insert a door lock request 19521da177e4SLinus Torvalds * onto the head of the SCSI request queue for the device. There 19531da177e4SLinus Torvalds * is no point trying to lock the door of an off-line device. 19541da177e4SLinus Torvalds */ 19551da177e4SLinus Torvalds shost_for_each_device(sdev, shost) { 195648379270SChristoph Hellwig if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) { 19571da177e4SLinus Torvalds scsi_eh_lock_door(sdev); 195848379270SChristoph Hellwig sdev->was_reset = 0; 195948379270SChristoph Hellwig } 19601da177e4SLinus Torvalds } 19611da177e4SLinus Torvalds 19621da177e4SLinus Torvalds /* 19631da177e4SLinus Torvalds * next free up anything directly waiting upon the host. this 19641da177e4SLinus Torvalds * will be requests for character device operations, and also for 19651da177e4SLinus Torvalds * ioctls to queued block devices. 19661da177e4SLinus Torvalds */ 1967b4562022SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 196891921e01SHannes Reinecke shost_printk(KERN_INFO, shost, "waking up host to restart\n")); 19691da177e4SLinus Torvalds 1970939647eeSJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 1971939647eeSJames Bottomley if (scsi_host_set_state(shost, SHOST_RUNNING)) 1972939647eeSJames Bottomley if (scsi_host_set_state(shost, SHOST_CANCEL)) 1973939647eeSJames Bottomley BUG_ON(scsi_host_set_state(shost, SHOST_DEL)); 1974939647eeSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 19751da177e4SLinus Torvalds 19761da177e4SLinus Torvalds wake_up(&shost->host_wait); 19771da177e4SLinus Torvalds 19781da177e4SLinus Torvalds /* 19791da177e4SLinus Torvalds * finally we need to re-initiate requests that may be pending. we will 19801da177e4SLinus Torvalds * have had everything blocked while error handling is taking place, and 19811da177e4SLinus Torvalds * now that error recovery is done, we will need to ensure that these 19821da177e4SLinus Torvalds * requests are started. 19831da177e4SLinus Torvalds */ 19841da177e4SLinus Torvalds scsi_run_host_queues(shost); 198557fc2e33SDan Williams 198657fc2e33SDan Williams /* 198757fc2e33SDan Williams * if eh is active and host_eh_scheduled is pending we need to re-run 198857fc2e33SDan Williams * recovery. we do this check after scsi_run_host_queues() to allow 198957fc2e33SDan Williams * everything pent up since the last eh run a chance to make forward 199057fc2e33SDan Williams * progress before we sync again. Either we'll immediately re-run 199157fc2e33SDan Williams * recovery or scsi_device_unbusy() will wake us again when these 199257fc2e33SDan Williams * pending commands complete. 199357fc2e33SDan Williams */ 199457fc2e33SDan Williams spin_lock_irqsave(shost->host_lock, flags); 199557fc2e33SDan Williams if (shost->host_eh_scheduled) 199657fc2e33SDan Williams if (scsi_host_set_state(shost, SHOST_RECOVERY)) 199757fc2e33SDan Williams WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)); 199857fc2e33SDan Williams spin_unlock_irqrestore(shost->host_lock, flags); 19991da177e4SLinus Torvalds } 20001da177e4SLinus Torvalds 20011da177e4SLinus Torvalds /** 20021da177e4SLinus Torvalds * scsi_eh_ready_devs - check device ready state and recover if not. 20031da177e4SLinus Torvalds * @shost: host to be recovered. 2004eb44820cSRob Landley * @work_q: &list_head for pending commands. 2005eb44820cSRob Landley * @done_q: &list_head for processed commands. 2006dc8875e1SRandy Dunlap */ 2007dca84e46SDarrick J. Wong void scsi_eh_ready_devs(struct Scsi_Host *shost, 20081da177e4SLinus Torvalds struct list_head *work_q, 20091da177e4SLinus Torvalds struct list_head *done_q) 20101da177e4SLinus Torvalds { 20111da177e4SLinus Torvalds if (!scsi_eh_stu(shost, work_q, done_q)) 20121da177e4SLinus Torvalds if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) 201330bd7df8SMike Christie if (!scsi_eh_target_reset(shost, work_q, done_q)) 20141da177e4SLinus Torvalds if (!scsi_eh_bus_reset(shost, work_q, done_q)) 201591921e01SHannes Reinecke if (!scsi_eh_host_reset(shost, work_q, done_q)) 201630bd7df8SMike Christie scsi_eh_offline_sdevs(work_q, 201730bd7df8SMike Christie done_q); 20181da177e4SLinus Torvalds } 2019dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); 20201da177e4SLinus Torvalds 20211da177e4SLinus Torvalds /** 20221da177e4SLinus Torvalds * scsi_eh_flush_done_q - finish processed commands or retry them. 20231da177e4SLinus Torvalds * @done_q: list_head of processed commands. 2024dc8875e1SRandy Dunlap */ 2025041c5fc3STejun Heo void scsi_eh_flush_done_q(struct list_head *done_q) 20261da177e4SLinus Torvalds { 2027937abeaaSChristoph Hellwig struct scsi_cmnd *scmd, *next; 20281da177e4SLinus Torvalds 2029937abeaaSChristoph Hellwig list_for_each_entry_safe(scmd, next, done_q, eh_entry) { 2030937abeaaSChristoph Hellwig list_del_init(&scmd->eh_entry); 20311da177e4SLinus Torvalds if (scsi_device_online(scmd->device) && 20324a27446fSMike Christie !scsi_noretry_cmd(scmd) && 20338884efabSBrian King (++scmd->retries <= scmd->allowed)) { 203491921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 203591921e01SHannes Reinecke scmd_printk(KERN_INFO, scmd, 2036470613b4SHannes Reinecke "%s: flush retry cmd\n", 2037470613b4SHannes Reinecke current->comm)); 20381da177e4SLinus Torvalds scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); 20391da177e4SLinus Torvalds } else { 2040793698ceSPatrick Mansfield /* 2041793698ceSPatrick Mansfield * If just we got sense for the device (called 2042793698ceSPatrick Mansfield * scsi_eh_get_sense), scmd->result is already 2043793698ceSPatrick Mansfield * set, do not set DRIVER_TIMEOUT. 2044793698ceSPatrick Mansfield */ 20451da177e4SLinus Torvalds if (!scmd->result) 20461da177e4SLinus Torvalds scmd->result |= (DRIVER_TIMEOUT << 24); 204791921e01SHannes Reinecke SCSI_LOG_ERROR_RECOVERY(3, 204891921e01SHannes Reinecke scmd_printk(KERN_INFO, scmd, 2049470613b4SHannes Reinecke "%s: flush finish cmd\n", 2050470613b4SHannes Reinecke current->comm)); 20511da177e4SLinus Torvalds scsi_finish_command(scmd); 20521da177e4SLinus Torvalds } 20531da177e4SLinus Torvalds } 20541da177e4SLinus Torvalds } 2055041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_flush_done_q); 20561da177e4SLinus Torvalds 20571da177e4SLinus Torvalds /** 20581da177e4SLinus Torvalds * scsi_unjam_host - Attempt to fix a host which has a cmd that failed. 20591da177e4SLinus Torvalds * @shost: Host to unjam. 20601da177e4SLinus Torvalds * 20611da177e4SLinus Torvalds * Notes: 20621da177e4SLinus Torvalds * When we come in here, we *know* that all commands on the bus have 20631da177e4SLinus Torvalds * either completed, failed or timed out. we also know that no further 20641da177e4SLinus Torvalds * commands are being sent to the host, so things are relatively quiet 20651da177e4SLinus Torvalds * and we have freedom to fiddle with things as we wish. 20661da177e4SLinus Torvalds * 20671da177e4SLinus Torvalds * This is only the *default* implementation. it is possible for 20681da177e4SLinus Torvalds * individual drivers to supply their own version of this function, and 20691da177e4SLinus Torvalds * if the maintainer wishes to do this, it is strongly suggested that 20701da177e4SLinus Torvalds * this function be taken as a template and modified. this function 20711da177e4SLinus Torvalds * was designed to correctly handle problems for about 95% of the 20721da177e4SLinus Torvalds * different cases out there, and it should always provide at least a 20731da177e4SLinus Torvalds * reasonable amount of error recovery. 20741da177e4SLinus Torvalds * 20751da177e4SLinus Torvalds * Any command marked 'failed' or 'timeout' must eventually have 20761da177e4SLinus Torvalds * scsi_finish_cmd() called for it. we do all of the retry stuff 20771da177e4SLinus Torvalds * here, so when we restart the host after we return it should have an 20781da177e4SLinus Torvalds * empty queue. 2079dc8875e1SRandy Dunlap */ 20801da177e4SLinus Torvalds static void scsi_unjam_host(struct Scsi_Host *shost) 20811da177e4SLinus Torvalds { 20821da177e4SLinus Torvalds unsigned long flags; 20831da177e4SLinus Torvalds LIST_HEAD(eh_work_q); 20841da177e4SLinus Torvalds LIST_HEAD(eh_done_q); 20851da177e4SLinus Torvalds 20861da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 20871da177e4SLinus Torvalds list_splice_init(&shost->eh_cmd_q, &eh_work_q); 20881da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q)); 20911da177e4SLinus Torvalds 20921da177e4SLinus Torvalds if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q)) 20931da177e4SLinus Torvalds scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); 20941da177e4SLinus Torvalds 2095b4562022SHannes Reinecke spin_lock_irqsave(shost->host_lock, flags); 2096bb3b621aSRen Mingxin if (shost->eh_deadline != -1) 2097b4562022SHannes Reinecke shost->last_reset = 0; 2098b4562022SHannes Reinecke spin_unlock_irqrestore(shost->host_lock, flags); 20991da177e4SLinus Torvalds scsi_eh_flush_done_q(&eh_done_q); 21001da177e4SLinus Torvalds } 21011da177e4SLinus Torvalds 21021da177e4SLinus Torvalds /** 2103ad42eb1bSChristoph Hellwig * scsi_error_handler - SCSI error handler thread 21041da177e4SLinus Torvalds * @data: Host for which we are running. 21051da177e4SLinus Torvalds * 21061da177e4SLinus Torvalds * Notes: 2107ad42eb1bSChristoph Hellwig * This is the main error handling loop. This is run as a kernel thread 2108ad42eb1bSChristoph Hellwig * for every SCSI host and handles all error handling activity. 2109dc8875e1SRandy Dunlap */ 21101da177e4SLinus Torvalds int scsi_error_handler(void *data) 21111da177e4SLinus Torvalds { 2112ad42eb1bSChristoph Hellwig struct Scsi_Host *shost = data; 21131da177e4SLinus Torvalds 21141da177e4SLinus Torvalds /* 2115ad42eb1bSChristoph Hellwig * We use TASK_INTERRUPTIBLE so that the thread is not 2116ad42eb1bSChristoph Hellwig * counted against the load average as a running process. 2117ad42eb1bSChristoph Hellwig * We never actually get interrupted because kthread_run 2118c03264a7SFrederik Schwarzer * disables signal delivery for the created thread. 21191da177e4SLinus Torvalds */ 2120537b604cSMichal Hocko while (true) { 2121537b604cSMichal Hocko /* 2122537b604cSMichal Hocko * The sequence in kthread_stop() sets the stop flag first 2123537b604cSMichal Hocko * then wakes the process. To avoid missed wakeups, the task 2124537b604cSMichal Hocko * should always be in a non running state before the stop 2125537b604cSMichal Hocko * flag is checked 2126537b604cSMichal Hocko */ 2127b9d5c6b7SDan Williams set_current_state(TASK_INTERRUPTIBLE); 2128537b604cSMichal Hocko if (kthread_should_stop()) 2129537b604cSMichal Hocko break; 2130537b604cSMichal Hocko 2131ee7863bcSTejun Heo if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || 213274665016SChristoph Hellwig shost->host_failed != atomic_read(&shost->host_busy)) { 2133ad42eb1bSChristoph Hellwig SCSI_LOG_ERROR_RECOVERY(1, 213491921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 213591921e01SHannes Reinecke "scsi_eh_%d: sleeping\n", 21363ed7a470SJames Bottomley shost->host_no)); 21373ed7a470SJames Bottomley schedule(); 21383ed7a470SJames Bottomley continue; 21393ed7a470SJames Bottomley } 21401da177e4SLinus Torvalds 21413ed7a470SJames Bottomley __set_current_state(TASK_RUNNING); 2142ad42eb1bSChristoph Hellwig SCSI_LOG_ERROR_RECOVERY(1, 214391921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 214491921e01SHannes Reinecke "scsi_eh_%d: waking up %d/%d/%d\n", 2145b4562022SHannes Reinecke shost->host_no, shost->host_eh_scheduled, 214674665016SChristoph Hellwig shost->host_failed, 214774665016SChristoph Hellwig atomic_read(&shost->host_busy))); 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds /* 21501da177e4SLinus Torvalds * We have a host that is failing for some reason. Figure out 21511da177e4SLinus Torvalds * what we need to do to get it up and online again (if we can). 21521da177e4SLinus Torvalds * If we fail, we end up taking the thing offline. 21531da177e4SLinus Torvalds */ 2154ae0751ffSLin Ming if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) { 2155bc4f2401SAlan Stern SCSI_LOG_ERROR_RECOVERY(1, 2156a222b1e2SHannes Reinecke shost_printk(KERN_ERR, shost, 2157a222b1e2SHannes Reinecke "scsi_eh_%d: unable to autoresume\n", 2158bc4f2401SAlan Stern shost->host_no)); 2159bc4f2401SAlan Stern continue; 2160bc4f2401SAlan Stern } 2161bc4f2401SAlan Stern 21629227c33dSChristoph Hellwig if (shost->transportt->eh_strategy_handler) 21639227c33dSChristoph Hellwig shost->transportt->eh_strategy_handler(shost); 21641da177e4SLinus Torvalds else 21651da177e4SLinus Torvalds scsi_unjam_host(shost); 21661da177e4SLinus Torvalds 216772d8c36eSWei Fang /* All scmds have been handled */ 216872d8c36eSWei Fang shost->host_failed = 0; 216972d8c36eSWei Fang 21701da177e4SLinus Torvalds /* 21711da177e4SLinus Torvalds * Note - if the above fails completely, the action is to take 21721da177e4SLinus Torvalds * individual devices offline and flush the queue of any 21731da177e4SLinus Torvalds * outstanding requests that may have been pending. When we 21741da177e4SLinus Torvalds * restart, we restart any I/O to any other devices on the bus 21751da177e4SLinus Torvalds * which are still online. 21761da177e4SLinus Torvalds */ 21771da177e4SLinus Torvalds scsi_restart_operations(shost); 2178ae0751ffSLin Ming if (!shost->eh_noresume) 2179bc4f2401SAlan Stern scsi_autopm_put_host(shost); 21801da177e4SLinus Torvalds } 2181461a0ffbSSteven Rostedt __set_current_state(TASK_RUNNING); 2182461a0ffbSSteven Rostedt 2183ad42eb1bSChristoph Hellwig SCSI_LOG_ERROR_RECOVERY(1, 218491921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 218591921e01SHannes Reinecke "Error handler scsi_eh_%d exiting\n", 218691921e01SHannes Reinecke shost->host_no)); 21873ed7a470SJames Bottomley shost->ehandler = NULL; 21881da177e4SLinus Torvalds return 0; 21891da177e4SLinus Torvalds } 21901da177e4SLinus Torvalds 21911da177e4SLinus Torvalds /* 21921da177e4SLinus Torvalds * Function: scsi_report_bus_reset() 21931da177e4SLinus Torvalds * 21941da177e4SLinus Torvalds * Purpose: Utility function used by low-level drivers to report that 21951da177e4SLinus Torvalds * they have observed a bus reset on the bus being handled. 21961da177e4SLinus Torvalds * 21971da177e4SLinus Torvalds * Arguments: shost - Host in question 21981da177e4SLinus Torvalds * channel - channel on which reset was observed. 21991da177e4SLinus Torvalds * 22001da177e4SLinus Torvalds * Returns: Nothing 22011da177e4SLinus Torvalds * 22021da177e4SLinus Torvalds * Lock status: Host lock must be held. 22031da177e4SLinus Torvalds * 22041da177e4SLinus Torvalds * Notes: This only needs to be called if the reset is one which 22051da177e4SLinus Torvalds * originates from an unknown location. Resets originated 22061da177e4SLinus Torvalds * by the mid-level itself don't need to call this, but there 22071da177e4SLinus Torvalds * should be no harm. 22081da177e4SLinus Torvalds * 22091da177e4SLinus Torvalds * The main purpose of this is to make sure that a CHECK_CONDITION 22101da177e4SLinus Torvalds * is properly treated. 22111da177e4SLinus Torvalds */ 22121da177e4SLinus Torvalds void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) 22131da177e4SLinus Torvalds { 22141da177e4SLinus Torvalds struct scsi_device *sdev; 22151da177e4SLinus Torvalds 22161da177e4SLinus Torvalds __shost_for_each_device(sdev, shost) { 221730bd7df8SMike Christie if (channel == sdev_channel(sdev)) 221830bd7df8SMike Christie __scsi_report_device_reset(sdev, NULL); 22191da177e4SLinus Torvalds } 22201da177e4SLinus Torvalds } 22211da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_bus_reset); 22221da177e4SLinus Torvalds 22231da177e4SLinus Torvalds /* 22241da177e4SLinus Torvalds * Function: scsi_report_device_reset() 22251da177e4SLinus Torvalds * 22261da177e4SLinus Torvalds * Purpose: Utility function used by low-level drivers to report that 22271da177e4SLinus Torvalds * they have observed a device reset on the device being handled. 22281da177e4SLinus Torvalds * 22291da177e4SLinus Torvalds * Arguments: shost - Host in question 22301da177e4SLinus Torvalds * channel - channel on which reset was observed 22311da177e4SLinus Torvalds * target - target on which reset was observed 22321da177e4SLinus Torvalds * 22331da177e4SLinus Torvalds * Returns: Nothing 22341da177e4SLinus Torvalds * 22351da177e4SLinus Torvalds * Lock status: Host lock must be held 22361da177e4SLinus Torvalds * 22371da177e4SLinus Torvalds * Notes: This only needs to be called if the reset is one which 22381da177e4SLinus Torvalds * originates from an unknown location. Resets originated 22391da177e4SLinus Torvalds * by the mid-level itself don't need to call this, but there 22401da177e4SLinus Torvalds * should be no harm. 22411da177e4SLinus Torvalds * 22421da177e4SLinus Torvalds * The main purpose of this is to make sure that a CHECK_CONDITION 22431da177e4SLinus Torvalds * is properly treated. 22441da177e4SLinus Torvalds */ 22451da177e4SLinus Torvalds void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) 22461da177e4SLinus Torvalds { 22471da177e4SLinus Torvalds struct scsi_device *sdev; 22481da177e4SLinus Torvalds 22491da177e4SLinus Torvalds __shost_for_each_device(sdev, shost) { 2250422c0d61SJeff Garzik if (channel == sdev_channel(sdev) && 225130bd7df8SMike Christie target == sdev_id(sdev)) 225230bd7df8SMike Christie __scsi_report_device_reset(sdev, NULL); 22531da177e4SLinus Torvalds } 22541da177e4SLinus Torvalds } 22551da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_device_reset); 22561da177e4SLinus Torvalds 22571da177e4SLinus Torvalds static void 22581da177e4SLinus Torvalds scsi_reset_provider_done_command(struct scsi_cmnd *scmd) 22591da177e4SLinus Torvalds { 22601da177e4SLinus Torvalds } 22611da177e4SLinus Torvalds 2262176aa9d6SChristoph Hellwig /** 2263176aa9d6SChristoph Hellwig * scsi_ioctl_reset: explicitly reset a host/bus/target/device 2264176aa9d6SChristoph Hellwig * @dev: scsi_device to operate on 2265176aa9d6SChristoph Hellwig * @arg: reset type (see sg.h) 22661da177e4SLinus Torvalds */ 22671da177e4SLinus Torvalds int 2268176aa9d6SChristoph Hellwig scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) 22691da177e4SLinus Torvalds { 2270bc4f2401SAlan Stern struct scsi_cmnd *scmd; 2271d7a1bb0aSJames Smart struct Scsi_Host *shost = dev->host; 2272e9c787e6SChristoph Hellwig struct request *rq; 2273d7a1bb0aSJames Smart unsigned long flags; 2274176aa9d6SChristoph Hellwig int error = 0, rtn, val; 2275176aa9d6SChristoph Hellwig 2276176aa9d6SChristoph Hellwig if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 2277176aa9d6SChristoph Hellwig return -EACCES; 2278176aa9d6SChristoph Hellwig 2279176aa9d6SChristoph Hellwig error = get_user(val, arg); 2280176aa9d6SChristoph Hellwig if (error) 2281176aa9d6SChristoph Hellwig return error; 22821da177e4SLinus Torvalds 2283bc4f2401SAlan Stern if (scsi_autopm_get_host(shost) < 0) 2284176aa9d6SChristoph Hellwig return -EIO; 2285bc4f2401SAlan Stern 2286176aa9d6SChristoph Hellwig error = -EIO; 2287e9c787e6SChristoph Hellwig rq = kzalloc(sizeof(struct request) + sizeof(struct scsi_cmnd) + 2288e9c787e6SChristoph Hellwig shost->hostt->cmd_size, GFP_KERNEL); 2289e9c787e6SChristoph Hellwig if (!rq) 229095eeb5f5SChristoph Hellwig goto out_put_autopm_host; 2291e9c787e6SChristoph Hellwig blk_rq_init(NULL, rq); 229295eeb5f5SChristoph Hellwig 2293e9c787e6SChristoph Hellwig scmd = (struct scsi_cmnd *)(rq + 1); 2294e9c787e6SChristoph Hellwig scsi_init_command(dev, scmd); 2295e9c787e6SChristoph Hellwig scmd->request = rq; 229682ed4db4SChristoph Hellwig scmd->cmnd = scsi_req(rq)->cmd; 22971da177e4SLinus Torvalds 22981da177e4SLinus Torvalds scmd->scsi_done = scsi_reset_provider_done_command; 229930b0c37bSBoaz Harrosh memset(&scmd->sdb, 0, sizeof(scmd->sdb)); 23001da177e4SLinus Torvalds 23011da177e4SLinus Torvalds scmd->cmd_len = 0; 23021da177e4SLinus Torvalds 23031da177e4SLinus Torvalds scmd->sc_data_direction = DMA_BIDIRECTIONAL; 23041da177e4SLinus Torvalds 2305d7a1bb0aSJames Smart spin_lock_irqsave(shost->host_lock, flags); 2306d7a1bb0aSJames Smart shost->tmf_in_progress = 1; 2307d7a1bb0aSJames Smart spin_unlock_irqrestore(shost->host_lock, flags); 2308d7a1bb0aSJames Smart 2309176aa9d6SChristoph Hellwig switch (val & ~SG_SCSI_RESET_NO_ESCALATE) { 2310176aa9d6SChristoph Hellwig case SG_SCSI_RESET_NOTHING: 2311176aa9d6SChristoph Hellwig rtn = SUCCESS; 2312176aa9d6SChristoph Hellwig break; 2313176aa9d6SChristoph Hellwig case SG_SCSI_RESET_DEVICE: 23141da177e4SLinus Torvalds rtn = scsi_try_bus_device_reset(scmd); 2315176aa9d6SChristoph Hellwig if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) 23161da177e4SLinus Torvalds break; 23171da177e4SLinus Torvalds /* FALLTHROUGH */ 2318176aa9d6SChristoph Hellwig case SG_SCSI_RESET_TARGET: 231930bd7df8SMike Christie rtn = scsi_try_target_reset(scmd); 2320176aa9d6SChristoph Hellwig if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) 232130bd7df8SMike Christie break; 232230bd7df8SMike Christie /* FALLTHROUGH */ 2323176aa9d6SChristoph Hellwig case SG_SCSI_RESET_BUS: 23241da177e4SLinus Torvalds rtn = scsi_try_bus_reset(scmd); 2325176aa9d6SChristoph Hellwig if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) 23261da177e4SLinus Torvalds break; 23271da177e4SLinus Torvalds /* FALLTHROUGH */ 2328176aa9d6SChristoph Hellwig case SG_SCSI_RESET_HOST: 23291da177e4SLinus Torvalds rtn = scsi_try_host_reset(scmd); 2330176aa9d6SChristoph Hellwig if (rtn == SUCCESS) 233126cf591eSDouglas Gilbert break; 2332176aa9d6SChristoph Hellwig /* FALLTHROUGH */ 23333bf2ff67SBart Van Assche default: 23341da177e4SLinus Torvalds rtn = FAILED; 2335176aa9d6SChristoph Hellwig break; 23361da177e4SLinus Torvalds } 23371da177e4SLinus Torvalds 2338176aa9d6SChristoph Hellwig error = (rtn == SUCCESS) ? 0 : -EIO; 2339176aa9d6SChristoph Hellwig 2340d7a1bb0aSJames Smart spin_lock_irqsave(shost->host_lock, flags); 2341d7a1bb0aSJames Smart shost->tmf_in_progress = 0; 2342d7a1bb0aSJames Smart spin_unlock_irqrestore(shost->host_lock, flags); 2343d7a1bb0aSJames Smart 2344d7a1bb0aSJames Smart /* 2345d7a1bb0aSJames Smart * be sure to wake up anyone who was sleeping or had their queue 2346d7a1bb0aSJames Smart * suspended while we performed the TMF. 2347d7a1bb0aSJames Smart */ 2348d7a1bb0aSJames Smart SCSI_LOG_ERROR_RECOVERY(3, 234991921e01SHannes Reinecke shost_printk(KERN_INFO, shost, 235091921e01SHannes Reinecke "waking up host to restart after TMF\n")); 2351d7a1bb0aSJames Smart 2352d7a1bb0aSJames Smart wake_up(&shost->host_wait); 2353d7a1bb0aSJames Smart scsi_run_host_queues(shost); 2354d7a1bb0aSJames Smart 23550f121dd8SChristoph Hellwig scsi_put_command(scmd); 2356e9c787e6SChristoph Hellwig kfree(rq); 23570f121dd8SChristoph Hellwig 235804796336SChristoph Hellwig out_put_autopm_host: 2359bc4f2401SAlan Stern scsi_autopm_put_host(shost); 2360176aa9d6SChristoph Hellwig return error; 23611da177e4SLinus Torvalds } 2362176aa9d6SChristoph Hellwig EXPORT_SYMBOL(scsi_ioctl_reset); 23631da177e4SLinus Torvalds 23644753cbc0SHannes Reinecke bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd, 23651da177e4SLinus Torvalds struct scsi_sense_hdr *sshdr) 23661da177e4SLinus Torvalds { 23671da177e4SLinus Torvalds return scsi_normalize_sense(cmd->sense_buffer, 2368b80ca4f7SFUJITA Tomonori SCSI_SENSE_BUFFERSIZE, sshdr); 23691da177e4SLinus Torvalds } 23701da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_command_normalize_sense); 23711da177e4SLinus Torvalds 23721da177e4SLinus Torvalds /** 2373eb44820cSRob Landley * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format) 23741da177e4SLinus Torvalds * @sense_buffer: byte array of sense data 23751da177e4SLinus Torvalds * @sb_len: number of valid bytes in sense_buffer 23761da177e4SLinus Torvalds * @info_out: pointer to 64 integer where 8 or 4 byte information 23771da177e4SLinus Torvalds * field will be placed if found. 23781da177e4SLinus Torvalds * 23791da177e4SLinus Torvalds * Return value: 23802908769cSDamien Le Moal * true if information field found, false if not found. 2381dc8875e1SRandy Dunlap */ 23822908769cSDamien Le Moal bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len, 23831da177e4SLinus Torvalds u64 *info_out) 23841da177e4SLinus Torvalds { 23851da177e4SLinus Torvalds const u8 * ucp; 23861da177e4SLinus Torvalds 23871da177e4SLinus Torvalds if (sb_len < 7) 23882908769cSDamien Le Moal return false; 23891da177e4SLinus Torvalds switch (sense_buffer[0] & 0x7f) { 23901da177e4SLinus Torvalds case 0x70: 23911da177e4SLinus Torvalds case 0x71: 23921da177e4SLinus Torvalds if (sense_buffer[0] & 0x80) { 23932908769cSDamien Le Moal *info_out = get_unaligned_be32(&sense_buffer[3]); 23942908769cSDamien Le Moal return true; 23952908769cSDamien Le Moal } 23962908769cSDamien Le Moal return false; 23971da177e4SLinus Torvalds case 0x72: 23981da177e4SLinus Torvalds case 0x73: 23991da177e4SLinus Torvalds ucp = scsi_sense_desc_find(sense_buffer, sb_len, 24001da177e4SLinus Torvalds 0 /* info desc */); 24011da177e4SLinus Torvalds if (ucp && (0xa == ucp[1])) { 24022908769cSDamien Le Moal *info_out = get_unaligned_be64(&ucp[4]); 24032908769cSDamien Le Moal return true; 24041da177e4SLinus Torvalds } 24052908769cSDamien Le Moal return false; 24061da177e4SLinus Torvalds default: 24072908769cSDamien Le Moal return false; 24081da177e4SLinus Torvalds } 24091da177e4SLinus Torvalds } 24101da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_sense_info_fld); 2411