Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 252447
b: refs/heads/master
c: 3eef625
h: refs/heads/master
i:
  252445: 5eeada1
  252443: 69792a6
  252439: dc56081
  252431: 9b63bc0
  252415: e5875fe
v: v3
  • Loading branch information
David Jeffery authored and James Bottomley committed May 24, 2011
1 parent f911169 commit 102abfd
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 21 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: 0bcaa11154f07502e68375617e5650173eea8e50
refs/heads/master: 3eef6257de48ff84a5d98ca533685df8a3beaeb8
87 changes: 67 additions & 20 deletions trunk/drivers/scsi/scsi_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#define BUS_RESET_SETTLE_TIME (10)
#define HOST_RESET_SETTLE_TIME (10)

static int scsi_eh_try_stu(struct scsi_cmnd *scmd);

/* called with shost->host_lock held */
void scsi_eh_wakeup(struct Scsi_Host *shost)
{
Expand Down Expand Up @@ -946,6 +948,48 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
}
}

/**
* scsi_eh_test_devices - check if devices are responding from error recovery.
* @cmd_list: scsi commands in error recovery.
* @work_q: queue for commands which still need more error recovery
* @done_q: queue for commands which are finished
* @try_stu: boolean on if a STU command should be tried in addition to TUR.
*
* Decription:
* Tests if devices are in a working state. Commands to devices now in
* a working state are sent to the done_q while commands to devices which
* are still failing to respond are returned to the work_q for more
* processing.
**/
static int scsi_eh_test_devices(struct list_head *cmd_list,
struct list_head *work_q,
struct list_head *done_q, int try_stu)
{
struct scsi_cmnd *scmd, *next;
struct scsi_device *sdev;
int finish_cmds;

while (!list_empty(cmd_list)) {
scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
sdev = scmd->device;

finish_cmds = !scsi_device_online(scmd->device) ||
(try_stu && !scsi_eh_try_stu(scmd) &&
!scsi_eh_tur(scmd)) ||
!scsi_eh_tur(scmd);

list_for_each_entry_safe(scmd, next, cmd_list, eh_entry)
if (scmd->device == sdev) {
if (finish_cmds)
scsi_eh_finish_cmd(scmd, done_q);
else
list_move_tail(&scmd->eh_entry, work_q);
}
}
return list_empty(work_q);
}


/**
* scsi_eh_abort_cmds - abort pending commands.
* @work_q: &list_head for pending commands.
Expand All @@ -962,6 +1006,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
struct list_head *done_q)
{
struct scsi_cmnd *scmd, *next;
LIST_HEAD(check_list);
int rtn;

list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
Expand All @@ -973,11 +1018,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd);
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
if (!scsi_device_online(scmd->device) ||
rtn == FAST_IO_FAIL ||
!scsi_eh_tur(scmd)) {
if (rtn == FAST_IO_FAIL)
scsi_eh_finish_cmd(scmd, done_q);
}
else
list_move_tail(&scmd->eh_entry, &check_list);
} else
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
" cmd failed:"
Expand All @@ -986,7 +1030,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
scmd));
}

return list_empty(work_q);
return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
}

/**
Expand Down Expand Up @@ -1137,6 +1181,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
struct list_head *done_q)
{
LIST_HEAD(tmp_list);
LIST_HEAD(check_list);

list_splice_init(work_q, &tmp_list);

Expand All @@ -1161,17 +1206,17 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
if (scmd_id(scmd) != id)
continue;

if ((rtn == SUCCESS || rtn == FAST_IO_FAIL)
&& (!scsi_device_online(scmd->device) ||
rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd)))
if (rtn == SUCCESS)
list_move_tail(&scmd->eh_entry, &check_list);
else if (rtn == FAST_IO_FAIL)
scsi_eh_finish_cmd(scmd, done_q);
else
/* push back on work queue for further processing */
list_move(&scmd->eh_entry, work_q);
}
}

return list_empty(work_q);
return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
}

/**
Expand All @@ -1185,6 +1230,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
struct list_head *done_q)
{
struct scsi_cmnd *scmd, *chan_scmd, *next;
LIST_HEAD(check_list);
unsigned int channel;
int rtn;

Expand Down Expand Up @@ -1216,12 +1262,14 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
rtn = scsi_try_bus_reset(chan_scmd);
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (channel == scmd_channel(scmd))
if (!scsi_device_online(scmd->device) ||
rtn == FAST_IO_FAIL ||
!scsi_eh_tur(scmd))
if (channel == scmd_channel(scmd)) {
if (rtn == FAST_IO_FAIL)
scsi_eh_finish_cmd(scmd,
done_q);
else
list_move_tail(&scmd->eh_entry,
&check_list);
}
}
} else {
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST"
Expand All @@ -1230,7 +1278,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
channel));
}
}
return list_empty(work_q);
return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
}

/**
Expand All @@ -1242,6 +1290,7 @@ static int scsi_eh_host_reset(struct list_head *work_q,
struct list_head *done_q)
{
struct scsi_cmnd *scmd, *next;
LIST_HEAD(check_list);
int rtn;

if (!list_empty(work_q)) {
Expand All @@ -1252,12 +1301,10 @@ static int scsi_eh_host_reset(struct list_head *work_q,
, current->comm));

rtn = scsi_try_host_reset(scmd);
if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
if (rtn == SUCCESS) {
list_splice_init(work_q, &check_list);
} else if (rtn == FAST_IO_FAIL) {
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (!scsi_device_online(scmd->device) ||
rtn == FAST_IO_FAIL ||
(!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) ||
!scsi_eh_tur(scmd))
scsi_eh_finish_cmd(scmd, done_q);
}
} else {
Expand All @@ -1266,7 +1313,7 @@ static int scsi_eh_host_reset(struct list_head *work_q,
current->comm));
}
}
return list_empty(work_q);
return scsi_eh_test_devices(&check_list, work_q, done_q, 1);
}

/**
Expand Down

0 comments on commit 102abfd

Please sign in to comment.