[PATCH] SCSI: sd_suspend: evaluate lower layers' returns

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



commit 867780e1bbc4c9deed13397fbd80119f431d557f
Author: Oliver Neukum <oliver@xxxxxxxxxx>
Date:   Mon Oct 18 19:09:26 2010 +0200

    SCSI: sd_suspend: evaluate lower layers' returns
    
    sd_suspend() sends down commands that may fail.
    Depending on the reason of failure the failures
    can be ignored, the suspension retried or aborted.
    This patch evaluates the error returns from the lower
    layers to do so.
    
    Signed-off-by: Oliver Neukum <oneukum@xxxxxxx>

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ffa0689..fa695c4 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1081,11 +1081,32 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
 		sd_print_result(sdkp, res);
 		if (driver_byte(res) & DRIVER_SENSE)
 			sd_print_sense_hdr(sdkp, &sshdr);
-	}
 
-	if (res)
-		return -EIO;
-	return 0;
+		/* we need to evaluate the error return  */
+		if ((scsi_sense_valid(&sshdr) &&
+			/* 0x3a is medium not present */
+			sshdr.asc == 0x3a))
+			/* this is no error here */
+			return 0;
+
+		switch (host_byte(res)) {
+		/* ignore errors due to racing a disconnection */
+		case DID_BAD_TARGET:
+		case DID_NO_CONNECT:	
+			return 0;
+		/* signal the upper layer it might try again */
+		case DID_BUS_BUSY:
+		case DID_ABORT:
+		case DID_RESET:
+		case DID_IMM_RETRY:
+		case DID_SOFT_ERROR:
+			return -EBUSY;
+		default:
+			return -EIO;
+		}
+	} else {
+		return 0;
+	}
 }
 
 static void sd_rescan(struct device *dev)
@@ -2474,9 +2495,13 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
 		sd_print_result(sdkp, res);
 		if (driver_byte(res) & DRIVER_SENSE)
 			sd_print_sense_hdr(sdkp, &sshdr);
+		/* no medium -> nobody cares */
+		if (scsi_sense_valid(&sshdr) && sshdr.asc == 0x3a)
+			return 0;
 	}
 
-	return res;
+	/* error returns should conform what the pm core expects */
+	return res ? -EIO : 0;
 }
 
 /*
@@ -2522,6 +2547,9 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
 	if ((mesg.event & PM_EVENT_SLEEP) && sdkp->device->manage_start_stop) {
 		sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
 		ret = sd_start_stop_device(sdkp, 0);
+		/* an error is not worth aborting a system sleep */
+		if (!(mesg.event & PM_EVENT_AUTO))
+			ret = 0;
 	}
 
 done:
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux