@ -105,7 +105,8 @@ static void sd_unlock_native_capacity(struct gendisk *disk);
static int sd_probe ( struct device * ) ;
static int sd_remove ( struct device * ) ;
static void sd_shutdown ( struct device * ) ;
static int sd_suspend ( struct device * ) ;
static int sd_suspend_system ( struct device * ) ;
static int sd_suspend_runtime ( struct device * ) ;
static int sd_resume ( struct device * ) ;
static void sd_rescan ( struct device * ) ;
static int sd_done ( struct scsi_cmnd * ) ;
@ -484,11 +485,11 @@ static struct class sd_disk_class = {
} ;
static const struct dev_pm_ops sd_pm_ops = {
. suspend = sd_suspend ,
. suspend = sd_suspend_system ,
. resume = sd_resume ,
. poweroff = sd_suspend ,
. poweroff = sd_suspend_system ,
. restore = sd_resume ,
. runtime_suspend = sd_suspend ,
. runtime_suspend = sd_suspend_runtime ,
. runtime_resume = sd_resume ,
} ;
@ -1438,7 +1439,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
if ( ! scsi_device_online ( sdp ) )
return - ENODEV ;
for ( retries = 3 ; retries > 0 ; - - retries ) {
unsigned char cmd [ 10 ] = { 0 } ;
@ -1456,12 +1456,31 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
if ( res ) {
sd_print_result ( sdkp , res ) ;
if ( driver_byte ( res ) & DRIVER_SENSE )
sd_print_sense_hdr ( sdkp , & sshdr ) ;
/* 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_IMM_RETRY :
case DID_REQUEUE :
case DID_SOFT_ERROR :
return - EBUSY ;
default :
return - EIO ;
}
}
if ( res )
return - EIO ;
return 0 ;
}
@ -3061,9 +3080,17 @@ 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 ) ;
if ( scsi_sense_valid ( & sshdr ) & &
/* 0x3a is medium not present */
sshdr . asc = = 0x3a )
res = 0 ;
}
return res ;
/* SCSI error codes must not go to the generic layer */
if ( res )
return - EIO ;
return 0 ;
}
/*
@ -3081,7 +3108,7 @@ static void sd_shutdown(struct device *dev)
if ( pm_runtime_suspended ( dev ) )
goto exit ;
if ( sdkp - > WCE ) {
if ( sdkp - > WCE & & sdkp - > media_present ) {
sd_printk ( KERN_NOTICE , sdkp , " Synchronizing SCSI cache \n " ) ;
sd_sync_cache ( sdkp ) ;
}
@ -3095,7 +3122,7 @@ exit:
scsi_disk_put ( sdkp ) ;
}
static int sd_suspend ( struct device * dev )
static int sd_suspend_common ( struct device * dev , bool ignore_stop_errors )
{
struct scsi_disk * sdkp = scsi_disk_get_from_dev ( dev ) ;
int ret = 0 ;
@ -3103,16 +3130,23 @@ static int sd_suspend(struct device *dev)
if ( ! sdkp )
return 0 ; /* this can happen */
if ( sdkp - > WCE ) {
if ( sdkp - > WCE & & sdkp - > media_present ) {
sd_printk ( KERN_NOTICE , sdkp , " Synchronizing SCSI cache \n " ) ;
ret = sd_sync_cache ( sdkp ) ;
if ( ret )
if ( ret ) {
/* ignore OFFLINE device */
if ( ret = = - ENODEV )
ret = 0 ;
goto done ;
}
}
if ( sdkp - > device - > manage_start_stop ) {
sd_printk ( KERN_NOTICE , sdkp , " Stopping disk \n " ) ;
/* an error is not worth aborting a system sleep */
ret = sd_start_stop_device ( sdkp , 0 ) ;
if ( ignore_stop_errors )
ret = 0 ;
}
done :
@ -3120,6 +3154,16 @@ done:
return ret ;
}
static int sd_suspend_system ( struct device * dev )
{
return sd_suspend_common ( dev , true ) ;
}
static int sd_suspend_runtime ( struct device * dev )
{
return sd_suspend_common ( dev , false ) ;
}
static int sd_resume ( struct device * dev )
{
struct scsi_disk * sdkp = scsi_disk_get_from_dev ( dev ) ;