SCSI: fix crashes in sd and sr runtime PM
[pandora-kernel.git] / drivers / scsi / sd.c
index 6dace1a..9a4f52d 100644 (file)
@@ -641,10 +641,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 
 static void sd_unprep_fn(struct request_queue *q, struct request *rq)
 {
+       struct scsi_cmnd *SCpnt = rq->special;
+
        if (rq->cmd_flags & REQ_DISCARD) {
                free_page((unsigned long)rq->buffer);
                rq->buffer = NULL;
        }
+       if (SCpnt->cmnd != rq->cmd) {
+               mempool_free(SCpnt->cmnd, sd_cdb_pool);
+               SCpnt->cmnd = NULL;
+               SCpnt->cmd_len = 0;
+       }
 }
 
 /**
@@ -1331,6 +1338,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
 {
        u64 start_lba = blk_rq_pos(scmd->request);
        u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
+       u64 factor = scmd->device->sector_size / 512;
        u64 bad_lba;
        int info_valid;
        /*
@@ -1352,16 +1360,9 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
        if (scsi_bufflen(scmd) <= scmd->device->sector_size)
                return 0;
 
-       if (scmd->device->sector_size < 512) {
-               /* only legitimate sector_size here is 256 */
-               start_lba <<= 1;
-               end_lba <<= 1;
-       } else {
-               /* be careful ... don't want any overflows */
-               u64 factor = scmd->device->sector_size / 512;
-               do_div(start_lba, factor);
-               do_div(end_lba, factor);
-       }
+       /* be careful ... don't want any overflows */
+       do_div(start_lba, factor);
+       do_div(end_lba, factor);
 
        /* The bad lba was reported incorrectly, we have no idea where
         * the error is.
@@ -1452,21 +1453,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
                sd_dif_complete(SCpnt, good_bytes);
 
-       if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
-           == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) {
-
-               /* We have to print a failed command here as the
-                * extended CDB gets freed before scsi_io_completion()
-                * is called.
-                */
-               if (result)
-                       scsi_print_command(SCpnt);
-
-               mempool_free(SCpnt->cmnd, sd_cdb_pool);
-               SCpnt->cmnd = NULL;
-               SCpnt->cmd_len = 0;
-       }
-
        return good_bytes;
 }
 
@@ -1903,8 +1889,7 @@ got_data:
        if (sector_size != 512 &&
            sector_size != 1024 &&
            sector_size != 2048 &&
-           sector_size != 4096 &&
-           sector_size != 256) {
+           sector_size != 4096) {
                sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n",
                          sector_size);
                /*
@@ -1953,8 +1938,6 @@ got_data:
                sdkp->capacity <<= 2;
        else if (sector_size == 1024)
                sdkp->capacity <<= 1;
-       else if (sector_size == 256)
-               sdkp->capacity >>= 1;
 
        blk_queue_physical_block_size(sdp->request_queue,
                                      sdkp->physical_block_size);
@@ -2144,14 +2127,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
                        }
                }
 
-               if (modepage == 0x3F) {
-                       sd_printk(KERN_ERR, sdkp, "No Caching mode page "
-                                 "present\n");
-                       goto defaults;
-               } else if ((buffer[offset] & 0x3f) != modepage) {
-                       sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
-                       goto defaults;
-               }
+               sd_printk(KERN_ERR, sdkp, "No Caching mode page found\n");
+               goto defaults;
+
        Page_found:
                if (modepage == 8) {
                        sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
@@ -2162,7 +2140,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
                }
 
                sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
-               if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+               if (sdp->broken_fua) {
+                       sd_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
+                       sdkp->DPOFUA = 0;
+               } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
                        sd_printk(KERN_NOTICE, sdkp,
                                  "Uses READ/WRITE(6), disabling FUA\n");
                        sdkp->DPOFUA = 0;
@@ -2786,8 +2767,8 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
        int ret = 0;
 
-       if (!sdkp)
-               return 0;       /* this can happen */
+       if (!sdkp)      /* E.g.: runtime suspend following sd_remove() */
+               return 0;
 
        if (sdkp->WCE) {
                sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
@@ -2811,6 +2792,9 @@ static int sd_resume(struct device *dev)
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
        int ret = 0;
 
+       if (!sdkp)      /* E.g.: runtime resume at the start of sd_probe() */
+               return 0;
+
        if (!sdkp->device->manage_start_stop)
                goto done;