Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 32744
b: refs/heads/master
c: 631c228
h: refs/heads/master
v: v3
  • Loading branch information
Christoph Hellwig authored and James Bottomley committed Jul 9, 2006
1 parent 15ebb00 commit b9a30e9
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 234 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ae0fda0cdf009731a33f031f86df8566f1977ffe
refs/heads/master: 631c228cd09bd5b93090fa60bd9803ec14aa0586
14 changes: 9 additions & 5 deletions trunk/drivers/scsi/aha152x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
DECLARE_MUTEX_LOCKED(sem);
struct timer_list timer;
int ret, issued, disconnected;
unsigned char old_cmd_len = SCpnt->cmd_len;
unsigned short old_use_sg = SCpnt->use_sg;
void *old_buffer = SCpnt->request_buffer;
unsigned old_bufflen = SCpnt->request_bufflen;
unsigned long flags;

#if defined(AHA152X_DEBUG)
Expand Down Expand Up @@ -1212,11 +1216,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
add_timer(&timer);
down(&sem);
del_timer(&timer);
SCpnt->cmd_len = SCpnt->old_cmd_len;
SCpnt->use_sg = SCpnt->old_use_sg;
SCpnt->request_buffer = SCpnt->buffer;
SCpnt->request_bufflen = SCpnt->bufflen;

SCpnt->cmd_len = old_cmd_len;
SCpnt->use_sg = old_use_sg;
SCpnt->request_buffer = old_buffer;
SCpnt->request_bufflen = old_bufflen;

DO_LOCK(flags);

Expand Down
11 changes: 1 addition & 10 deletions trunk/drivers/scsi/scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ void scsi_log_send(struct scsi_cmnd *cmd)
if (level > 3) {
printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
" done = 0x%p, queuecommand 0x%p\n",
cmd->buffer, cmd->bufflen,
cmd->request_buffer, cmd->request_bufflen,
cmd->done,
sdev->host->hostt->queuecommand);

Expand Down Expand Up @@ -661,11 +661,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
*/
int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
*/
scsi_setup_cmd_retry(cmd);

/*
* Zero the sense information from the last time we tried
* this command.
Expand Down Expand Up @@ -711,10 +706,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
"Notifying upper driver of completion "
"(result %x)\n", cmd->result));

/*
* We can get here with use_sg=0, causing a panic in the upper level
*/
cmd->use_sg = cmd->old_use_sg;
cmd->done(cmd);
}
EXPORT_SYMBOL(scsi_finish_command);
Expand Down
210 changes: 89 additions & 121 deletions trunk/drivers/scsi/scsi_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,19 +460,67 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
* Return value:
* SUCCESS or FAILED or NEEDS_RETRY
**/
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
{
struct scsi_device *sdev = scmd->device;
struct Scsi_Host *shost = sdev->host;
int old_result = scmd->result;
DECLARE_COMPLETION(done);
unsigned long timeleft;
unsigned long flags;
unsigned char old_cmnd[MAX_COMMAND_SIZE];
enum dma_data_direction old_data_direction;
unsigned short old_use_sg;
unsigned char old_cmd_len;
unsigned old_bufflen;
void *old_buffer;
int rtn;

/*
* We need saved copies of a number of fields - this is because
* error handling may need to overwrite these with different values
* to run different commands, and once error handling is complete,
* we will need to restore these values prior to running the actual
* command.
*/
old_buffer = scmd->request_buffer;
old_bufflen = scmd->request_bufflen;
memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
old_data_direction = scmd->sc_data_direction;
old_cmd_len = scmd->cmd_len;
old_use_sg = scmd->use_sg;

if (copy_sense) {
int gfp_mask = GFP_ATOMIC;

if (shost->hostt->unchecked_isa_dma)
gfp_mask |= __GFP_DMA;

scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->request_bufflen = 252;
scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask);
if (!scmd->request_buffer)
return FAILED;
} else {
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->sc_data_direction = DMA_NONE;
}

scmd->underflow = 0;
scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);

if (sdev->scsi_level <= SCSI_2)
scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
(sdev->lun << 5 & 0xe0);

/*
* Zero the sense buffer. The scsi spec mandates that any
* untransferred sense data should be interpreted as being zero.
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));

shost->eh_action = &done;

spin_lock_irqsave(shost->host_lock, flags);
Expand Down Expand Up @@ -522,6 +570,29 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
rtn = FAILED;
}


/*
* Last chance to have valid sense data.
*/
if (copy_sense) {
if (!SCSI_SENSE_VALID(scmd)) {
memcpy(scmd->sense_buffer, scmd->request_buffer,
sizeof(scmd->sense_buffer));
}
kfree(scmd->request_buffer);
}


/*
* Restore original data
*/
scmd->request_buffer = old_buffer;
scmd->request_bufflen = old_bufflen;
memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
scmd->sc_data_direction = old_data_direction;
scmd->cmd_len = old_cmd_len;
scmd->use_sg = old_use_sg;
scmd->result = old_result;
return rtn;
}

Expand All @@ -537,56 +608,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
static int scsi_request_sense(struct scsi_cmnd *scmd)
{
static unsigned char generic_sense[6] =
{REQUEST_SENSE, 0, 0, 0, 252, 0};
unsigned char *scsi_result;
int saved_result;
int rtn;
{REQUEST_SENSE, 0, 0, 0, 252, 0};

memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));

scsi_result = kmalloc(252, GFP_ATOMIC | ((scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0));


if (unlikely(!scsi_result)) {
printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
__FUNCTION__);
return FAILED;
}

/*
* zero the sense buffer. some host adapters automatically always
* request sense, so it is not a good idea that
* scmd->request_buffer and scmd->sense_buffer point to the same
* address (db). 0 is not a valid sense code.
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
memset(scsi_result, 0, 252);

saved_result = scmd->result;
scmd->request_buffer = scsi_result;
scmd->request_bufflen = 252;
scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
scmd->sc_data_direction = DMA_FROM_DEVICE;
scmd->underflow = 0;

rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);

/* last chance to have valid sense data */
if(!SCSI_SENSE_VALID(scmd)) {
memcpy(scmd->sense_buffer, scmd->request_buffer,
sizeof(scmd->sense_buffer));
}

kfree(scsi_result);

/*
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
*/
scsi_setup_cmd_retry(scmd);
scmd->result = saved_result;
return rtn;
return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
}

/**
Expand All @@ -605,12 +630,6 @@ void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
{
scmd->device->host->host_failed--;
scmd->eh_eflags = 0;

/*
* set this back so that the upper level can correctly free up
* things.
*/
scsi_setup_cmd_retry(scmd);
list_move_tail(&scmd->eh_entry, done_q);
}
EXPORT_SYMBOL(scsi_eh_finish_cmd);
Expand Down Expand Up @@ -715,47 +734,26 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
{
static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
int retry_cnt = 1, rtn;
int saved_result;

retry_tur:
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));

/*
* zero the sense buffer. the scsi spec mandates that any
* untransferred sense data should be interpreted as being zero.
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));

saved_result = scmd->result;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
scmd->underflow = 0;
scmd->sc_data_direction = DMA_NONE;

rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);

/*
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
*/
scsi_setup_cmd_retry(scmd);
scmd->result = saved_result;

/*
* hey, we are done. let's look to see what happened.
*/
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
__FUNCTION__, scmd, rtn));
if (rtn == SUCCESS)
return 0;
else if (rtn == NEEDS_RETRY) {

switch (rtn) {
case NEEDS_RETRY:
if (retry_cnt--)
goto retry_tur;
/*FALLTHRU*/
case SUCCESS:
return 0;
default:
return 1;
}
return 1;
}

/**
Expand Down Expand Up @@ -837,44 +835,16 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
{
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
int rtn;
int saved_result;

if (!scmd->device->allow_restart)
return 1;

memcpy(scmd->cmnd, stu_command, sizeof(stu_command));

/*
* zero the sense buffer. the scsi spec mandates that any
* untransferred sense data should be interpreted as being zero.
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));

saved_result = scmd->result;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->use_sg = 0;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
scmd->underflow = 0;
scmd->sc_data_direction = DMA_NONE;
if (scmd->device->allow_restart) {
int rtn;

rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT);

/*
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
*/
scsi_setup_cmd_retry(scmd);
scmd->result = saved_result;
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
if (rtn == SUCCESS)
return 0;
}

/*
* hey, we are done. let's look to see what happened.
*/
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
__FUNCTION__, scmd, rtn));
if (rtn == SUCCESS)
return 0;
return 1;
}

Expand Down Expand Up @@ -1684,8 +1654,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)

scmd->scsi_done = scsi_reset_provider_done_command;
scmd->done = NULL;
scmd->buffer = NULL;
scmd->bufflen = 0;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;

Expand Down
Loading

0 comments on commit b9a30e9

Please sign in to comment.