📄 scsi_obsolete.c
字号:
} printk("scsi : aborting command due to timeout : pid %lu, scsi%d," " channel %d, id %d, lun %d ", SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel, (int) SCpnt->target, (int) SCpnt->lun); print_command(SCpnt->cmnd); if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) return 0; SCpnt->abort_reason = why; switch (host->hostt->abort(SCpnt)) { /* We do not know how to abort. Try waiting another * time increment and see if this helps. Set the * WAS_TIMEDOUT flag set so we do not try this twice */ case SCSI_ABORT_BUSY: /* Tough call - returning 1 from * this is too severe */ case SCSI_ABORT_SNOOZE: if (why == DID_TIME_OUT) { SCpnt->internal_timeout &= ~IN_ABORT; if (SCpnt->flags & WAS_TIMEDOUT) { return 1; /* Indicate we cannot handle this. * We drop down into the reset handler * and try again */ } else { SCpnt->flags |= WAS_TIMEDOUT; oldto = SCpnt->timeout_per_command; update_timeout(SCpnt, oldto); } } return 0; case SCSI_ABORT_PENDING: if (why != DID_TIME_OUT) { update_timeout(SCpnt, oldto); } return 0; case SCSI_ABORT_SUCCESS: /* We should have already aborted this one. No * need to adjust timeout */ SCpnt->internal_timeout &= ~IN_ABORT; return 0; case SCSI_ABORT_NOT_RUNNING: SCpnt->internal_timeout &= ~IN_ABORT; update_timeout(SCpnt, 0); return 0; case SCSI_ABORT_ERROR: default: SCpnt->internal_timeout &= ~IN_ABORT; return 1; } } }}/* Mark a single SCSI Device as having been reset. */static inline void scsi_mark_device_reset(Scsi_Device * Device){ Device->was_reset = 1; Device->expecting_cc_ua = 1;}/* Mark all SCSI Devices on a specific Host as having been reset. */void scsi_mark_host_reset(struct Scsi_Host *Host){ Scsi_Cmnd *SCpnt; Scsi_Device *SDpnt; for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) { for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) scsi_mark_device_reset(SCpnt->device); }}/* Mark all SCSI Devices on a specific Host Bus as having been reset. */static void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel){ Scsi_Cmnd *SCpnt; Scsi_Device *SDpnt; for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) { for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) if (SCpnt->channel == channel) scsi_mark_device_reset(SCpnt->device); }}static int scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags){ int temp; Scsi_Cmnd *SCpnt1; Scsi_Device *SDpnt; struct Scsi_Host *host = SCpnt->host; printk("SCSI bus is being reset for host %d channel %d.\n", host->host_no, SCpnt->channel);#if 0 /* * First of all, we need to make a recommendation to the low-level * driver as to whether a BUS_DEVICE_RESET should be performed, * or whether we should do a full BUS_RESET. There is no simple * algorithm here - we basically use a series of heuristics * to determine what we should do. */ SCpnt->host->suggest_bus_reset = FALSE; /* * First see if all of the active devices on the bus have * been jammed up so that we are attempting resets. If so, * then suggest a bus reset. Forcing a bus reset could * result in some race conditions, but no more than * you would usually get with timeouts. We will cross * that bridge when we come to it. * * This is actually a pretty bad idea, since a sequence of * commands will often timeout together and this will cause a * Bus Device Reset followed immediately by a SCSI Bus Reset. * If all of the active devices really are jammed up, the * Bus Device Reset will quickly timeout and scsi_times_out * will follow up with a SCSI Bus Reset anyway. */ SCpnt1 = host->host_queue; while (SCpnt1) { if (SCpnt1->request.rq_status != RQ_INACTIVE && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0) break; SCpnt1 = SCpnt1->next; } if (SCpnt1 == NULL) { reset_flags |= SCSI_RESET_SUGGEST_BUS_RESET; } /* * If the code that called us is suggesting a hard reset, then * definitely request it. This usually occurs because a * BUS_DEVICE_RESET times out. * * Passing reset_flags along takes care of this automatically. */ if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) { SCpnt->host->suggest_bus_reset = TRUE; }#endif while (1) { /* * Protect against races here. If the command is done, or we are * on a different command forget it. */ if (reset_flags & SCSI_RESET_ASYNCHRONOUS) if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) { return 0; } if (SCpnt->internal_timeout & IN_RESET) { spin_unlock_irq(&io_request_lock); while (SCpnt->internal_timeout & IN_RESET) barrier(); spin_lock_irq(&io_request_lock); } else { SCpnt->internal_timeout |= IN_RESET; update_timeout(SCpnt, RESET_TIMEOUT); if (reset_flags & SCSI_RESET_SYNCHRONOUS) SCpnt->flags |= SYNC_RESET; if (host->host_busy) { for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { SCpnt1 = SDpnt->device_queue; while (SCpnt1) { if (SCpnt1->request.rq_status != RQ_INACTIVE) {#if 0 if (!(SCpnt1->flags & IS_RESETTING) && !(SCpnt1->internal_timeout & IN_ABORT)) scsi_abort(SCpnt1, DID_RESET);#endif SCpnt1->flags |= (WAS_RESET | IS_RESETTING); } SCpnt1 = SCpnt1->next; } } host->last_reset = jiffies; host->resetting = 1; /* * I suppose that the host reset callback will not play * with the resetting field. We have just set the resetting * flag here. -arca */ temp = host->hostt->reset(SCpnt, reset_flags); /* This test allows the driver to introduce an additional bus settle time delay by setting last_reset up to 20 seconds in the future. In the normal case where the driver does not modify last_reset, it must be assumed that the actual bus reset occurred immediately prior to the return to this code, and so last_reset must be updated to the current time, so that the delay in internal_cmnd will guarantee at least a MIN_RESET_DELAY bus settle time. */ if (host->last_reset - jiffies > 20UL * HZ) host->last_reset = jiffies; } else { host->host_busy++; host->last_reset = jiffies; host->resetting = 1; SCpnt->flags |= (WAS_RESET | IS_RESETTING); /* * I suppose that the host reset callback will not play * with the resetting field. We have just set the resetting * flag here. -arca */ temp = host->hostt->reset(SCpnt, reset_flags); if (time_before(host->last_reset, jiffies) || (time_after(host->last_reset, jiffies + 20 * HZ))) host->last_reset = jiffies; host->host_busy--; } if (reset_flags & SCSI_RESET_SYNCHRONOUS) SCpnt->flags &= ~SYNC_RESET;#ifdef DEBUG printk("scsi reset function returned %d\n", temp);#endif /* * Now figure out what we need to do, based upon * what the low level driver said that it did. * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING, * or SCSI_RESET_WAKEUP, then the low level driver did a * bus device reset or bus reset, so we should go through * and mark one or all of the devices on that bus * as having been reset. */ switch (temp & SCSI_RESET_ACTION) { case SCSI_RESET_SUCCESS: if (temp & SCSI_RESET_HOST_RESET) scsi_mark_host_reset(host); else if (temp & SCSI_RESET_BUS_RESET) scsi_mark_bus_reset(host, SCpnt->channel); else scsi_mark_device_reset(SCpnt->device); SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); return 0; case SCSI_RESET_PENDING: if (temp & SCSI_RESET_HOST_RESET) scsi_mark_host_reset(host); else if (temp & SCSI_RESET_BUS_RESET) scsi_mark_bus_reset(host, SCpnt->channel); else scsi_mark_device_reset(SCpnt->device); case SCSI_RESET_NOT_RUNNING: return 0; case SCSI_RESET_PUNT: SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); scsi_request_sense(SCpnt); return 0; case SCSI_RESET_WAKEUP: if (temp & SCSI_RESET_HOST_RESET) scsi_mark_host_reset(host); else if (temp & SCSI_RESET_BUS_RESET) scsi_mark_bus_reset(host, SCpnt->channel); else scsi_mark_device_reset(SCpnt->device); SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); scsi_request_sense(SCpnt); /* * If a bus reset was performed, we * need to wake up each and every command * that was active on the bus or if it was a HBA * reset all active commands on all channels */ if (temp & SCSI_RESET_HOST_RESET) { for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { SCpnt1 = SDpnt->device_queue; while (SCpnt1) { if (SCpnt1->request.rq_status != RQ_INACTIVE && SCpnt1 != SCpnt) scsi_request_sense(SCpnt1); SCpnt1 = SCpnt1->next; } } } else if (temp & SCSI_RESET_BUS_RESET) { for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) { SCpnt1 = SDpnt->device_queue; while (SCpnt1) { if (SCpnt1->request.rq_status != RQ_INACTIVE && SCpnt1 != SCpnt && SCpnt1->channel == SCpnt->channel) scsi_request_sense(SCpnt); SCpnt1 = SCpnt1->next; } } } return 0; case SCSI_RESET_SNOOZE: /* In this case, we set the timeout field to 0 * so that this command does not time out any more, * and we return 1 so that we get a message on the * screen. */ SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3); update_timeout(SCpnt, 0); /* If you snooze, you lose... */ case SCSI_RESET_ERROR: default: return 1; } return temp; } }}/* * The strategy is to cause the timer code to call scsi_times_out() * when the soonest timeout is pending. * The arguments are used when we are queueing a new command, because * we do not want to subtract the time used from this time, but when we * set the timer, we want to take this value into account. */int update_timeout(Scsi_Cmnd * SCset, int timeout){ int rtn; /* * We are using the new error handling code to actually register/deregister * timers for timeout. */ if (!timer_pending(&SCset->eh_timeout)) { rtn = 0; } else { rtn = SCset->eh_timeout.expires - jiffies; } if (timeout == 0) { scsi_delete_timer(SCset); } else { scsi_add_timer(SCset, timeout, scsi_old_times_out); } return rtn;}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -