Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / scsi_error.c
index c00f06e..08c06c5 100644 (file)
@@ -124,6 +124,17 @@ static bool scsi_cmd_retry_allowed(struct scsi_cmnd *cmd)
        return ++cmd->retries <= cmd->allowed;
 }
 
+static bool scsi_eh_should_retry_cmd(struct scsi_cmnd *cmd)
+{
+       struct scsi_device *sdev = cmd->device;
+       struct Scsi_Host *host = sdev->host;
+
+       if (host->hostt->eh_should_retry_cmd)
+               return  host->hostt->eh_should_retry_cmd(cmd);
+
+       return true;
+}
+
 /**
  * scmd_eh_abort_handler - Handle command aborts
  * @work:      command to be aborted.
@@ -159,7 +170,8 @@ scmd_eh_abort_handler(struct work_struct *work)
                                                    "eh timeout, not retrying "
                                                    "aborted command\n"));
                        } else if (!scsi_noretry_cmd(scmd) &&
-                                  scsi_cmd_retry_allowed(scmd)) {
+                                  scsi_cmd_retry_allowed(scmd) &&
+                               scsi_eh_should_retry_cmd(scmd)) {
                                SCSI_LOG_ERROR_RECOVERY(3,
                                        scmd_printk(KERN_WARNING, scmd,
                                                    "retry aborted command\n"));
@@ -1861,6 +1873,12 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
                 * the fast io fail tmo fired), so send IO directly upwards.
                 */
                return SUCCESS;
+       case DID_TRANSPORT_MARGINAL:
+               /*
+                * caller has decided not to do retries on
+                * abort success, so send IO directly upwards
+                */
+               return SUCCESS;
        case DID_ERROR:
                if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
                    status_byte(scmd->result) == RESERVATION_CONFLICT)
@@ -2105,7 +2123,8 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
        list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
                list_del_init(&scmd->eh_entry);
                if (scsi_device_online(scmd->device) &&
-                   !scsi_noretry_cmd(scmd) && scsi_cmd_retry_allowed(scmd)) {
+                   !scsi_noretry_cmd(scmd) && scsi_cmd_retry_allowed(scmd) &&
+                       scsi_eh_should_retry_cmd(scmd)) {
                        SCSI_LOG_ERROR_RECOVERY(3,
                                scmd_printk(KERN_INFO, scmd,
                                             "%s: flush retry cmd\n",