NVMe: Add translation for block limits
authorKeith Busch <keith.busch@intel.com>
Tue, 7 Apr 2015 21:34:18 +0000 (15:34 -0600)
committerJens Axboe <axboe@fb.com>
Wed, 8 Apr 2015 01:11:04 +0000 (19:11 -0600)
Adds SCSI-to-NVMe translation for VPD B0h, block limits inquiry data.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/nvme-scsi.c

index e10196e0182d450667cf886421e9475c218f30c8..6b736b00f63ebbbf01db7eb037695cbd77bca8c8 100644 (file)
@@ -55,6 +55,7 @@ static int sg_version_num = 30534;    /* 2 digits for each component */
 #define VPD_SERIAL_NUMBER                              0x80
 #define VPD_DEVICE_IDENTIFIERS                         0x83
 #define VPD_EXTENDED_INQUIRY                           0x86
+#define VPD_BLOCK_LIMITS                               0xB0
 #define VPD_BLOCK_DEV_CHARACTERISTICS                  0xB1
 
 /* CDB offsets */
@@ -132,9 +133,10 @@ static int sg_version_num = 30534; /* 2 digits for each component */
 #define INQ_UNIT_SERIAL_NUMBER_PAGE                    0x80
 #define INQ_DEVICE_IDENTIFICATION_PAGE                 0x83
 #define INQ_EXTENDED_INQUIRY_DATA_PAGE                 0x86
+#define INQ_BDEV_LIMITS_PAGE                           0xB0
 #define INQ_BDEV_CHARACTERISTICS_PAGE                  0xB1
 #define INQ_SERIAL_NUMBER_LENGTH                       0x14
-#define INQ_NUM_SUPPORTED_VPD_PAGES                    5
+#define INQ_NUM_SUPPORTED_VPD_PAGES                    6
 #define VERSION_SPC_4                                  0x06
 #define ACA_UNSUPPORTED                                        0
 #define STANDARD_INQUIRY_LENGTH                                36
@@ -747,6 +749,7 @@ static int nvme_trans_supported_vpd_pages(struct nvme_ns *ns,
        inq_response[6] = INQ_DEVICE_IDENTIFICATION_PAGE;
        inq_response[7] = INQ_EXTENDED_INQUIRY_DATA_PAGE;
        inq_response[8] = INQ_BDEV_CHARACTERISTICS_PAGE;
+       inq_response[9] = INQ_BDEV_LIMITS_PAGE;
 
        xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
        res = nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
@@ -938,6 +941,25 @@ static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
        return res;
 }
 
+static int nvme_trans_bdev_limits_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
+                                       u8 *inq_response, int alloc_len)
+{
+       __be32 max_sectors = cpu_to_be32(queue_max_hw_sectors(ns->queue));
+       __be32 max_discard = cpu_to_be32(ns->queue->limits.max_discard_sectors);
+       __be32 discard_desc_count = cpu_to_be32(0x100);
+
+       memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
+       inq_response[1] = VPD_BLOCK_LIMITS;
+       inq_response[3] = 0x3c; /* Page Length */
+       memcpy(&inq_response[8], &max_sectors, sizeof(u32));
+       memcpy(&inq_response[20], &max_discard, sizeof(u32));
+
+       if (max_discard)
+               memcpy(&inq_response[24], &discard_desc_count, sizeof(u32));
+
+       return nvme_trans_copy_to_user(hdr, inq_response, 0x3c);
+}
+
 static int nvme_trans_bdev_char_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
                                        int alloc_len)
 {
@@ -2268,6 +2290,10 @@ static int nvme_trans_inquiry(struct nvme_ns *ns, struct sg_io_hdr *hdr,
                case VPD_EXTENDED_INQUIRY:
                        res = nvme_trans_ext_inq_page(ns, hdr, alloc_len);
                        break;
+               case VPD_BLOCK_LIMITS:
+                       res = nvme_trans_bdev_limits_page(ns, hdr, inq_response,
+                                                               alloc_len);
+                       break;
                case VPD_BLOCK_DEV_CHARACTERISTICS:
                        res = nvme_trans_bdev_char_page(ns, hdr, alloc_len);
                        break;