--- linux-2.6.20-rc6nv/drivers/scsi/sd.c 2007-01-28 17:00:00.000000000 -0600 +++ linux-2.6.20-rc6nvedit/drivers/scsi/sd.c 2007-01-28 18:08:53.000000000 -0600 @@ -821,6 +821,39 @@ static int sd_sync_cache(struct scsi_dev return res; } +static int sd_stop_unit(struct scsi_device *sdp, struct scsi_disk* sdkp) +{ + int res; + struct scsi_sense_hdr sshdr; + unsigned char cmd[10] = { 0 }; + + if (!scsi_device_online(sdp)) + return -ENODEV; + + cmd[0] = START_STOP; + /* + * Leave the rest of the command zero to indicate + * transition to stopped power condition and return + * on completion. + */ + printk(KERN_NOTICE "Stopping SCSI disk %s\n", + sdkp->disk->disk_name); + res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); + + if (res) { + printk(KERN_WARNING "sd stop failed: status = %x, message = %02x, " + "host = %d, driver = %02x\n", + status_byte(res), msg_byte(res), + host_byte(res), driver_byte(res)); + if (driver_byte(res) & DRIVER_SENSE) + scsi_print_sense_hdr("sd", &sshdr); + } + + return res; +} + + static int sd_issue_flush(struct device *dev, sector_t *error_sector) { int ret = 0; @@ -1727,11 +1760,13 @@ static int sd_probe(struct device *dev) **/ static int sd_remove(struct device *dev) { + struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = dev_get_drvdata(dev); class_device_del(&sdkp->cdev); del_gendisk(sdkp->disk); sd_shutdown(dev); + sd_stop_unit(sdp,sdkp); mutex_lock(&sd_ref_mutex); dev_set_drvdata(dev, NULL); @@ -1784,6 +1819,9 @@ static void sd_shutdown(struct device *d sdkp->disk->disk_name); sd_sync_cache(sdp); } + if(system_state == SYSTEM_POWER_OFF) + sd_stop_unit(sdp,sdkp); + scsi_disk_put(sdkp); }