Merge tag 'aa-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmo...
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / sd.c
index 352bc77b7c886fb80c057019c3edc2d5b95b7d7e..c1c555242d0d715d46c051955deacea4a819d634 100644 (file)
@@ -105,7 +105,7 @@ 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 *, pm_message_t state);
+static int sd_suspend(struct device *);
 static int sd_resume(struct device *);
 static void sd_rescan(struct device *);
 static int sd_done(struct scsi_cmnd *);
@@ -142,6 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
        char *buffer_data;
        struct scsi_mode_data data;
        struct scsi_sense_hdr sshdr;
+       const char *temp = "temporary ";
        int len;
 
        if (sdp->type != TYPE_DISK)
@@ -150,6 +151,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
                 * it's not worth the risk */
                return -EINVAL;
 
+       if (strncmp(buf, temp, sizeof(temp) - 1) == 0) {
+               buf += sizeof(temp) - 1;
+               sdkp->cache_override = 1;
+       } else {
+               sdkp->cache_override = 0;
+       }
+
        for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
                len = strlen(sd_cache_types[i]);
                if (strncmp(sd_cache_types[i], buf, len) == 0 &&
@@ -162,6 +170,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
        rcd = ct & 0x01 ? 1 : 0;
        wce = ct & 0x02 ? 1 : 0;
+
+       if (sdkp->cache_override) {
+               sdkp->WCE = wce;
+               sdkp->RCD = rcd;
+               return count;
+       }
+
        if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
                            SD_MAX_RETRIES, &data, NULL))
                return -EINVAL;
@@ -465,15 +480,23 @@ static struct class sd_disk_class = {
        .dev_attrs      = sd_disk_attrs,
 };
 
+static const struct dev_pm_ops sd_pm_ops = {
+       .suspend                = sd_suspend,
+       .resume                 = sd_resume,
+       .poweroff               = sd_suspend,
+       .restore                = sd_resume,
+       .runtime_suspend        = sd_suspend,
+       .runtime_resume         = sd_resume,
+};
+
 static struct scsi_driver sd_template = {
        .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "sd",
                .probe          = sd_probe,
                .remove         = sd_remove,
-               .suspend        = sd_suspend,
-               .resume         = sd_resume,
                .shutdown       = sd_shutdown,
+               .pm             = &sd_pm_ops,
        },
        .rescan                 = sd_rescan,
        .done                   = sd_done,
@@ -1011,7 +1034,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff;
                SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff;
                SCpnt->cmnd[31] = (unsigned char) this_count & 0xff;
-       } else if (block > 0xffffffff) {
+       } else if (sdp->use_16_for_rw) {
                SCpnt->cmnd[0] += READ_16 - READ_6;
                SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0);
                SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
@@ -1113,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
 
        sdev = sdkp->device;
 
-       retval = scsi_autopm_get_device(sdev);
-       if (retval)
-               goto error_autopm;
-
        /*
         * If the device is in error recovery, wait until it is done.
         * If the device is offline, then disallow any access to it.
@@ -1161,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
        return 0;
 
 error_out:
-       scsi_autopm_put_device(sdev);
-error_autopm:
        scsi_disk_put(sdkp);
        return retval;  
 }
@@ -1180,7 +1197,7 @@ error_autopm:
  *
  *     Locking: called with bdev->bd_mutex held.
  **/
-static int sd_release(struct gendisk *disk, fmode_t mode)
+static void sd_release(struct gendisk *disk, fmode_t mode)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
        struct scsi_device *sdev = sdkp->device;
@@ -1197,9 +1214,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
         * XXX is followed by a "rmmod sd_mod"?
         */
 
-       scsi_autopm_put_device(sdev);
        scsi_disk_put(sdkp);
-       return 0;
 }
 
 static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
@@ -1359,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
        retval = -ENODEV;
 
        if (scsi_block_when_processing_errors(sdp)) {
-               retval = scsi_autopm_get_device(sdp);
-               if (retval)
-                       goto out;
-
                sshdr  = kzalloc(sizeof(*sshdr), GFP_KERNEL);
                retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
                                              sshdr);
-               scsi_autopm_put_device(sdp);
        }
 
        /* failed to execute TUR, assume media not present */
@@ -1416,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
                 * Leave the rest of the command zero to indicate
                 * flush everything.
                 */
-               res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                                      SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+               res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+                                            &sshdr, SD_FLUSH_TIMEOUT,
+                                            SD_MAX_RETRIES, NULL, REQ_PM);
                if (res == 0)
                        break;
        }
@@ -2203,6 +2214,8 @@ got_data:
                }
        }
 
+       sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
+
        /* Rescale capacity to 512-byte units */
        if (sector_size == 4096)
                sdkp->capacity <<= 3;
@@ -2309,6 +2322,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
        int old_rcd = sdkp->RCD;
        int old_dpofua = sdkp->DPOFUA;
 
+
+       if (sdkp->cache_override)
+               return;
+
        first_len = 4;
        if (sdp->skip_ms_page_8) {
                if (sdp->type == TYPE_RBC)
@@ -2802,6 +2819,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
        sdkp->capacity = 0;
        sdkp->media_present = 1;
        sdkp->write_prot = 0;
+       sdkp->cache_override = 0;
        sdkp->WCE = 0;
        sdkp->RCD = 0;
        sdkp->ATO = 0;
@@ -2828,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
+       blk_pm_runtime_init(sdp->request_queue, dev);
        scsi_autopm_put_device(sdp);
        put_device(&sdkp->dev);
 }
@@ -3011,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                              SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+       res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+                              SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
        if (res) {
                sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
                sd_print_result(sdkp, res);
@@ -3052,7 +3071,7 @@ exit:
        scsi_disk_put(sdkp);
 }
 
-static int sd_suspend(struct device *dev, pm_message_t mesg)
+static int sd_suspend(struct device *dev)
 {
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
        int ret = 0;
@@ -3067,7 +3086,7 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
                        goto done;
        }
 
-       if ((mesg.event & PM_EVENT_SLEEP) && sdkp->device->manage_start_stop) {
+       if (sdkp->device->manage_start_stop) {
                sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
                ret = sd_start_stop_device(sdkp, 0);
        }
@@ -3116,10 +3135,6 @@ static int __init init_sd(void)
        if (err)
                goto err_out;
 
-       err = scsi_register_driver(&sd_template.gendrv);
-       if (err)
-               goto err_out_class;
-
        sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
                                         0, 0, NULL);
        if (!sd_cdb_cache) {
@@ -3133,8 +3148,15 @@ static int __init init_sd(void)
                goto err_out_cache;
        }
 
+       err = scsi_register_driver(&sd_template.gendrv);
+       if (err)
+               goto err_out_driver;
+
        return 0;
 
+err_out_driver:
+       mempool_destroy(sd_cdb_pool);
+
 err_out_cache:
        kmem_cache_destroy(sd_cdb_cache);
 
@@ -3157,10 +3179,10 @@ static void __exit exit_sd(void)
 
        SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
+       scsi_unregister_driver(&sd_template.gendrv);
        mempool_destroy(sd_cdb_pool);
        kmem_cache_destroy(sd_cdb_cache);
 
-       scsi_unregister_driver(&sd_template.gendrv);
        class_unregister(&sd_disk_class);
 
        for (i = 0; i < SD_MAJORS; i++)