RISC-V: Move counter info definition to sbi header file
[linux-2.6-microblaze.git] / drivers / scsi / sd.c
index dc6e557..895b56c 100644 (file)
@@ -797,7 +797,6 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
        case SD_LBP_FULL:
        case SD_LBP_DISABLE:
                blk_queue_max_discard_sectors(q, 0);
-               blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
                return;
 
        case SD_LBP_UNMAP:
@@ -830,7 +829,6 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
        }
 
        blk_queue_max_discard_sectors(q, max_blocks * (logical_block_size >> 9));
-       blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
 }
 
 static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
@@ -2176,40 +2174,48 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
 {
        struct scsi_device *sdp = sdkp->device;
        u8 type;
-       int ret = 0;
 
        if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) {
                sdkp->protection_type = 0;
-               return ret;
+               return 0;
        }
 
        type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
 
-       if (type > T10_PI_TYPE3_PROTECTION)
-               ret = -ENODEV;
-       else if (scsi_host_dif_capable(sdp->host, type))
-               ret = 1;
-
-       if (sdkp->first_scan || type != sdkp->protection_type)
-               switch (ret) {
-               case -ENODEV:
-                       sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \
-                                 " protection type %u. Disabling disk!\n",
-                                 type);
-                       break;
-               case 1:
-                       sd_printk(KERN_NOTICE, sdkp,
-                                 "Enabling DIF Type %u protection\n", type);
-                       break;
-               case 0:
-                       sd_printk(KERN_NOTICE, sdkp,
-                                 "Disabling DIF Type %u protection\n", type);
-                       break;
-               }
+       if (type > T10_PI_TYPE3_PROTECTION) {
+               sd_printk(KERN_ERR, sdkp, "formatted with unsupported"  \
+                         " protection type %u. Disabling disk!\n",
+                         type);
+               sdkp->protection_type = 0;
+               return -ENODEV;
+       }
 
        sdkp->protection_type = type;
 
-       return ret;
+       return 0;
+}
+
+static void sd_config_protection(struct scsi_disk *sdkp)
+{
+       struct scsi_device *sdp = sdkp->device;
+
+       if (!sdkp->first_scan)
+               return;
+
+       sd_dif_config_host(sdkp);
+
+       if (!sdkp->protection_type)
+               return;
+
+       if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) {
+               sd_printk(KERN_NOTICE, sdkp,
+                         "Disabling DIF Type %u protection\n",
+                         sdkp->protection_type);
+               sdkp->protection_type = 0;
+       }
+
+       sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n",
+                 sdkp->protection_type);
 }
 
 static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
@@ -2843,40 +2849,37 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
-       unsigned int sector_sz = sdkp->device->sector_size;
-       const int vpd_len = 64;
-       unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
+       struct scsi_vpd *vpd;
 
-       if (!buffer ||
-           /* Block Limits VPD */
-           scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
-               goto out;
+       rcu_read_lock();
 
-       blk_queue_io_min(sdkp->disk->queue,
-                        get_unaligned_be16(&buffer[6]) * sector_sz);
+       vpd = rcu_dereference(sdkp->device->vpd_pgb0);
+       if (!vpd || vpd->len < 16)
+               goto out;
 
-       sdkp->max_xfer_blocks = get_unaligned_be32(&buffer[8]);
-       sdkp->opt_xfer_blocks = get_unaligned_be32(&buffer[12]);
+       sdkp->min_xfer_blocks = get_unaligned_be16(&vpd->data[6]);
+       sdkp->max_xfer_blocks = get_unaligned_be32(&vpd->data[8]);
+       sdkp->opt_xfer_blocks = get_unaligned_be32(&vpd->data[12]);
 
-       if (buffer[3] == 0x3c) {
+       if (vpd->len >= 64) {
                unsigned int lba_count, desc_count;
 
-               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
+               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&vpd->data[36]);
 
                if (!sdkp->lbpme)
                        goto out;
 
-               lba_count = get_unaligned_be32(&buffer[20]);
-               desc_count = get_unaligned_be32(&buffer[24]);
+               lba_count = get_unaligned_be32(&vpd->data[20]);
+               desc_count = get_unaligned_be32(&vpd->data[24]);
 
                if (lba_count && desc_count)
                        sdkp->max_unmap_blocks = lba_count;
 
-               sdkp->unmap_granularity = get_unaligned_be32(&buffer[28]);
+               sdkp->unmap_granularity = get_unaligned_be32(&vpd->data[28]);
 
-               if (buffer[32] & 0x80)
+               if (vpd->data[32] & 0x80)
                        sdkp->unmap_alignment =
-                               get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+                               get_unaligned_be32(&vpd->data[32]) & ~(1 << 31);
 
                if (!sdkp->lbpvpd) { /* LBP VPD page not provided */
 
@@ -2898,7 +2901,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        }
 
  out:
-       kfree(buffer);
+       rcu_read_unlock();
 }
 
 /**
@@ -2908,18 +2911,21 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 static void sd_read_block_characteristics(struct scsi_disk *sdkp)
 {
        struct request_queue *q = sdkp->disk->queue;
-       unsigned char *buffer;
+       struct scsi_vpd *vpd;
        u16 rot;
-       const int vpd_len = 64;
+       u8 zoned;
 
-       buffer = kmalloc(vpd_len, GFP_KERNEL);
+       rcu_read_lock();
+       vpd = rcu_dereference(sdkp->device->vpd_pgb1);
 
-       if (!buffer ||
-           /* Block Device Characteristics VPD */
-           scsi_get_vpd_page(sdkp->device, 0xb1, buffer, vpd_len))
-               goto out;
+       if (!vpd || vpd->len < 8) {
+               rcu_read_unlock();
+               return;
+       }
 
-       rot = get_unaligned_be16(&buffer[4]);
+       rot = get_unaligned_be16(&vpd->data[4]);
+       zoned = (vpd->data[8] >> 4) & 3;
+       rcu_read_unlock();
 
        if (rot == 1) {
                blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
@@ -2930,7 +2936,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
                /* Host-managed */
                blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HM);
        } else {
-               sdkp->zoned = (buffer[8] >> 4) & 3;
+               sdkp->zoned = zoned;
                if (sdkp->zoned == 1) {
                        /* Host-aware */
                        blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HA);
@@ -2941,7 +2947,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        }
 
        if (!sdkp->first_scan)
-               goto out;
+               return;
 
        if (blk_queue_is_zoned(q)) {
                sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
@@ -2954,9 +2960,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
                        sd_printk(KERN_NOTICE, sdkp,
                                  "Drive-managed SMR disk\n");
        }
-
- out:
-       kfree(buffer);
 }
 
 /**
@@ -2965,24 +2968,24 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
  */
 static void sd_read_block_provisioning(struct scsi_disk *sdkp)
 {
-       unsigned char *buffer;
-       const int vpd_len = 8;
+       struct scsi_vpd *vpd;
 
        if (sdkp->lbpme == 0)
                return;
 
-       buffer = kmalloc(vpd_len, GFP_KERNEL);
+       rcu_read_lock();
+       vpd = rcu_dereference(sdkp->device->vpd_pgb2);
 
-       if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
-               goto out;
+       if (!vpd || vpd->len < 8) {
+               rcu_read_unlock();
+               return;
+       }
 
        sdkp->lbpvpd    = 1;
-       sdkp->lbpu      = (buffer[5] >> 7) & 1; /* UNMAP */
-       sdkp->lbpws     = (buffer[5] >> 6) & 1; /* WRITE SAME(16) with UNMAP */
-       sdkp->lbpws10   = (buffer[5] >> 5) & 1; /* WRITE SAME(10) with UNMAP */
-
- out:
-       kfree(buffer);
+       sdkp->lbpu      = (vpd->data[5] >> 7) & 1; /* UNMAP */
+       sdkp->lbpws     = (vpd->data[5] >> 6) & 1; /* WRITE SAME(16) w/ UNMAP */
+       sdkp->lbpws10   = (vpd->data[5] >> 5) & 1; /* WRITE SAME(10) w/ UNMAP */
+       rcu_read_unlock();
 }
 
 static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
@@ -2996,8 +2999,7 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
        }
 
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
-               /* too large values might cause issues with arcmsr */
-               int vpd_buf_len = 64;
+               struct scsi_vpd *vpd;
 
                sdev->no_report_opcodes = 1;
 
@@ -3005,8 +3007,11 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
                 * CODES is unsupported and the device has an ATA
                 * Information VPD page (SAT).
                 */
-               if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len))
+               rcu_read_lock();
+               vpd = rcu_dereference(sdev->vpd_pg89);
+               if (vpd)
                        sdev->no_write_same = 1;
+               rcu_read_unlock();
        }
 
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
@@ -3110,6 +3115,29 @@ out:
        kfree(buffer);
 }
 
+static bool sd_validate_min_xfer_size(struct scsi_disk *sdkp)
+{
+       struct scsi_device *sdp = sdkp->device;
+       unsigned int min_xfer_bytes =
+               logical_to_bytes(sdp, sdkp->min_xfer_blocks);
+
+       if (sdkp->min_xfer_blocks == 0)
+               return false;
+
+       if (min_xfer_bytes & (sdkp->physical_block_size - 1)) {
+               sd_first_printk(KERN_WARNING, sdkp,
+                               "Preferred minimum I/O size %u bytes not a " \
+                               "multiple of physical block size (%u bytes)\n",
+                               min_xfer_bytes, sdkp->physical_block_size);
+               sdkp->min_xfer_blocks = 0;
+               return false;
+       }
+
+       sd_first_printk(KERN_INFO, sdkp, "Preferred minimum I/O size %u bytes\n",
+                       min_xfer_bytes);
+       return true;
+}
+
 /*
  * Determine the device's preferred I/O size for reads and writes
  * unless the reported value is unreasonably small, large, not a
@@ -3121,6 +3149,8 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
        struct scsi_device *sdp = sdkp->device;
        unsigned int opt_xfer_bytes =
                logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
+       unsigned int min_xfer_bytes =
+               logical_to_bytes(sdp, sdkp->min_xfer_blocks);
 
        if (sdkp->opt_xfer_blocks == 0)
                return false;
@@ -3149,6 +3179,15 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
                return false;
        }
 
+       if (min_xfer_bytes && opt_xfer_bytes % min_xfer_bytes) {
+               sd_first_printk(KERN_WARNING, sdkp,
+                               "Optimal transfer size %u bytes not a " \
+                               "multiple of preferred minimum block " \
+                               "size (%u bytes)\n",
+                               opt_xfer_bytes, min_xfer_bytes);
+               return false;
+       }
+
        if (opt_xfer_bytes & (sdkp->physical_block_size - 1)) {
                sd_first_printk(KERN_WARNING, sdkp,
                                "Optimal transfer size %u bytes not a " \
@@ -3226,6 +3265,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_app_tag_own(sdkp, buffer);
                sd_read_write_same(sdkp, buffer);
                sd_read_security(sdkp, buffer);
+               sd_config_protection(sdkp);
        }
 
        /*
@@ -3241,6 +3281,12 @@ static int sd_revalidate_disk(struct gendisk *disk)
        dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks);
        q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max);
 
+       if (sd_validate_min_xfer_size(sdkp))
+               blk_queue_io_min(sdkp->disk->queue,
+                                logical_to_bytes(sdp, sdkp->min_xfer_blocks));
+       else
+               blk_queue_io_min(sdkp->disk->queue, 0);
+
        if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
                q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
                rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
@@ -3475,15 +3521,10 @@ static int sd_probe(struct device *dev)
        error = device_add_disk(dev, gd, NULL);
        if (error) {
                put_device(&sdkp->disk_dev);
-               blk_cleanup_disk(gd);
+               put_disk(gd);
                goto out;
        }
 
-       if (sdkp->capacity)
-               sd_dif_config_host(sdkp);
-
-       sd_revalidate_disk(gd);
-
        if (sdkp->security) {
                sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit);
                if (sdkp->opal_dev)
@@ -3501,7 +3542,6 @@ static int sd_probe(struct device *dev)
  out_put:
        put_disk(gd);
  out_free:
-       sd_zbc_release_disk(sdkp);
        kfree(sdkp);
  out:
        scsi_autopm_put_device(sdp);
@@ -3538,7 +3578,7 @@ static void scsi_disk_release(struct device *dev)
        struct scsi_disk *sdkp = to_scsi_disk(dev);
 
        ida_free(&sd_index_ida, sdkp->index);
-       sd_zbc_release_disk(sdkp);
+       sd_zbc_free_zone_info(sdkp);
        put_device(&sdkp->device->sdev_gendev);
        free_opal_dev(sdkp->opal_dev);