📄 scsi_obsolete.c
字号:
return; } if (SCpnt->flags & WAS_SENSE) { SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->cmd_len = SCpnt->old_cmd_len; SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; SCpnt->underflow = SCpnt->old_underflow; } switch (host_byte(result)) { case DID_OK: if (status_byte(result) && (SCpnt->flags & WAS_SENSE)) /* Failed to obtain sense information */ { SCpnt->flags &= ~WAS_SENSE;#if 0 /* This cannot possibly be correct. */ SCpnt->internal_timeout &= ~SENSE_TIMEOUT;#endif if (!(SCpnt->flags & WAS_RESET)) { printk("scsi%d : channel %d target %d lun %d request sense" " failed, performing reset.\n", SCpnt->host->host_no, SCpnt->channel, SCpnt->target, SCpnt->lun); scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); status = REDO; break; } else { exit = (DRIVER_HARD | SUGGEST_ABORT); status = CMD_FINISHED; } } else switch (msg_byte(result)) { case COMMAND_COMPLETE: switch (status_byte(result)) { case GOOD: if (SCpnt->flags & WAS_SENSE) {#ifdef DEBUG printk("In scsi_done, GOOD status, COMMAND COMPLETE, " "parsing sense information.\n");#endif SCpnt->flags &= ~WAS_SENSE;#if 0 /* This cannot possibly be correct. */ SCpnt->internal_timeout &= ~SENSE_TIMEOUT;#endif switch (checked = check_sense(SCpnt)) { case SUGGEST_SENSE: case 0:#ifdef DEBUG printk("NO SENSE. status = REDO\n");#endif update_timeout(SCpnt, oldto); status = REDO; break; case SUGGEST_IS_OK: break; case SUGGEST_REMAP:#ifdef DEBUG printk("SENSE SUGGEST REMAP - status = CMD_FINISHED\n");#endif status = CMD_FINISHED; exit = DRIVER_SENSE | SUGGEST_ABORT; break; case SUGGEST_RETRY:#ifdef DEBUG printk("SENSE SUGGEST RETRY - status = MAYREDO\n");#endif status = MAYREDO; exit = DRIVER_SENSE | SUGGEST_RETRY; break; case SUGGEST_ABORT:#ifdef DEBUG printk("SENSE SUGGEST ABORT - status = CMD_FINISHED");#endif status = CMD_FINISHED; exit = DRIVER_SENSE | SUGGEST_ABORT; break; default: printk("Internal error %s %d \n", __FILE__, __LINE__); } } /* end WAS_SENSE */ else {#ifdef DEBUG printk("COMMAND COMPLETE message returned, " "status = CMD_FINISHED. \n");#endif exit = DRIVER_OK; status = CMD_FINISHED; } break; case CHECK_CONDITION: case COMMAND_TERMINATED: switch (check_sense(SCpnt)) { case 0: update_timeout(SCpnt, oldto); status = REDO; break; case SUGGEST_REMAP: status = CMD_FINISHED; exit = DRIVER_SENSE | SUGGEST_ABORT; break; case SUGGEST_RETRY: status = MAYREDO; exit = DRIVER_SENSE | SUGGEST_RETRY; break; case SUGGEST_ABORT: status = CMD_FINISHED; exit = DRIVER_SENSE | SUGGEST_ABORT; break; case SUGGEST_SENSE: scsi_request_sense(SCpnt); status = PENDING; break; } break; case CONDITION_GOOD: case INTERMEDIATE_GOOD: case INTERMEDIATE_C_GOOD: break; case BUSY: case QUEUE_FULL: update_timeout(SCpnt, oldto); status = REDO; break; case RESERVATION_CONFLICT: printk("scsi%d, channel %d : RESERVATION CONFLICT performing" " reset.\n", SCpnt->host->host_no, SCpnt->channel); scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); status = REDO; break; default: printk("Internal error %s %d \n" "status byte = %d \n", __FILE__, __LINE__, status_byte(result)); } break; default: panic("scsi: unsupported message byte %d received\n", msg_byte(result)); } break; case DID_TIME_OUT:#ifdef DEBUG printk("Host returned DID_TIME_OUT - ");#endif if (SCpnt->flags & WAS_TIMEDOUT) {#ifdef DEBUG printk("Aborting\n");#endif /* Allow TEST_UNIT_READY and INQUIRY commands to timeout early without causing resets. All other commands should be retried. */ if (SCpnt->cmnd[0] != TEST_UNIT_READY && SCpnt->cmnd[0] != INQUIRY) status = MAYREDO; exit = (DRIVER_TIMEOUT | SUGGEST_ABORT); } else {#ifdef DEBUG printk("Retrying.\n");#endif SCpnt->flags |= WAS_TIMEDOUT; SCpnt->internal_timeout &= ~IN_ABORT; status = REDO; } break; case DID_BUS_BUSY: case DID_PARITY: status = REDO; break; case DID_NO_CONNECT:#ifdef DEBUG printk("Couldn't connect.\n");#endif exit = (DRIVER_HARD | SUGGEST_ABORT); break; case DID_ERROR: status = MAYREDO; exit = (DRIVER_HARD | SUGGEST_ABORT); break; case DID_BAD_TARGET: case DID_ABORT: exit = (DRIVER_INVALID | SUGGEST_ABORT); break; case DID_RESET: if (SCpnt->flags & IS_RESETTING) { SCpnt->flags &= ~IS_RESETTING; status = REDO; break; } if (msg_byte(result) == GOOD && status_byte(result) == CHECK_CONDITION) { switch (check_sense(SCpnt)) { case 0: update_timeout(SCpnt, oldto); status = REDO; break; case SUGGEST_REMAP: case SUGGEST_RETRY: status = MAYREDO; exit = DRIVER_SENSE | SUGGEST_RETRY; break; case SUGGEST_ABORT: status = CMD_FINISHED; exit = DRIVER_SENSE | SUGGEST_ABORT; break; case SUGGEST_SENSE: scsi_request_sense(SCpnt); status = PENDING; break; } } else { status = REDO; exit = SUGGEST_RETRY; } break; default: exit = (DRIVER_ERROR | SUGGEST_DIE); } switch (status) { case CMD_FINISHED: case PENDING: break; case MAYREDO:#ifdef DEBUG printk("In MAYREDO, allowing %d retries, have %d\n", SCpnt->allowed, SCpnt->retries);#endif if ((++SCpnt->retries) < SCpnt->allowed) { if ((SCpnt->retries >= (SCpnt->allowed >> 1)) && !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD)) && !(SCpnt->flags & WAS_RESET)) { printk("scsi%d channel %d : resetting for second half of retries.\n", SCpnt->host->host_no, SCpnt->channel); scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); /* fall through to REDO */ } } else { status = CMD_FINISHED; break; } /* fall through to REDO */ case REDO: if (SCpnt->flags & WAS_SENSE) scsi_request_sense(SCpnt); else { memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd, sizeof(SCpnt->data_cmnd)); memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_bufflen = SCpnt->bufflen; SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->cmd_len = SCpnt->old_cmd_len; SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; SCpnt->underflow = SCpnt->old_underflow; SCpnt->result = 0; /* * Ugly, ugly. The newer interfaces all * assume that the lock isn't held. Mustn't * disappoint, or we deadlock the system. */ spin_unlock_irq(&io_request_lock); scsi_dispatch_cmd(SCpnt); spin_lock_irq(&io_request_lock); } break; default: INTERNAL_ERROR; } if (status == CMD_FINISHED) { Scsi_Request *SRpnt;#ifdef DEBUG printk("Calling done function - at address %p\n", SCpnt->done);#endif host->host_busy--; /* Indicate that we are free */ device->device_busy--; /* Decrement device usage counter. */ SCpnt->result = result | ((exit & 0xff) << 24); SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->cmd_len = SCpnt->old_cmd_len; SCpnt->sc_data_direction = SCpnt->sc_old_data_direction; SCpnt->underflow = SCpnt->old_underflow; /* * The upper layers assume the lock isn't held. We mustn't * disappoint them. When the new error handling code is in * use, the upper code is run from a bottom half handler, so * it isn't an issue. */ spin_unlock_irq(&io_request_lock); SRpnt = SCpnt->sc_request; if( SRpnt != NULL ) { SRpnt->sr_result = SRpnt->sr_command->result; if( SRpnt->sr_result != 0 ) { memcpy(SRpnt->sr_sense_buffer, SRpnt->sr_command->sense_buffer, sizeof(SRpnt->sr_sense_buffer)); } } SCpnt->done(SCpnt); spin_lock_irq(&io_request_lock); }#undef CMD_FINISHED#undef REDO#undef MAYREDO#undef PENDING}/* * The scsi_abort function interfaces with the abort() function of the host * we are aborting, and causes the current command to not complete. The * caller should deal with any error messages or status returned on the * next call. * * This will not be called reentrantly for a given host. *//* * Since we're nice guys and specified that abort() and reset() * can be non-reentrant. The internal_timeout flags are used for * this. */static int scsi_abort(Scsi_Cmnd * SCpnt, int why){ int oldto; struct Scsi_Host *host = SCpnt->host; while (1) { /* * Protect against races here. If the command is done, or we are * on a different command forget it. */ if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) { return 0; } if (SCpnt->internal_timeout & IN_ABORT) { spin_unlock_irq(&io_request_lock); while (SCpnt->internal_timeout & IN_ABORT) barrier(); spin_lock_irq(&io_request_lock); } else { SCpnt->internal_timeout |= IN_ABORT; oldto = update_timeout(SCpnt, ABORT_TIMEOUT); if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) { /* OK, this command must have died when we did the * reset. The device itself must have lied. */ printk("Stale command on %d %d:%d appears to have died when" " the bus was reset\n", SCpnt->channel, SCpnt->target, SCpnt->lun); } if (!host->host_busy) { SCpnt->internal_timeout &= ~IN_ABORT; update_timeout(SCpnt, oldto); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -