⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_obsolete.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			}			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 + -