Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
[firefly-linux-kernel-4.4.55.git] / drivers / nvdimm / core.c
index cf99cce8ef33a88733fa8b90754d559555026e4e..cb62ec6a12d073cf1abd5422e151636d57d6f781 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/libnvdimm.h>
 #include <linux/export.h>
 #include <linux/module.h>
+#include <linux/blkdev.h>
 #include <linux/device.h>
 #include <linux/ctype.h>
 #include <linux/ndctl.h>
@@ -173,6 +174,75 @@ int nd_uuid_store(struct device *dev, u8 **uuid_out, const char *buf,
        return 0;
 }
 
+ssize_t nd_sector_size_show(unsigned long current_lbasize,
+               const unsigned long *supported, char *buf)
+{
+       ssize_t len = 0;
+       int i;
+
+       for (i = 0; supported[i]; i++)
+               if (current_lbasize == supported[i])
+                       len += sprintf(buf + len, "[%ld] ", supported[i]);
+               else
+                       len += sprintf(buf + len, "%ld ", supported[i]);
+       len += sprintf(buf + len, "\n");
+       return len;
+}
+
+ssize_t nd_sector_size_store(struct device *dev, const char *buf,
+               unsigned long *current_lbasize, const unsigned long *supported)
+{
+       unsigned long lbasize;
+       int rc, i;
+
+       if (dev->driver)
+               return -EBUSY;
+
+       rc = kstrtoul(buf, 0, &lbasize);
+       if (rc)
+               return rc;
+
+       for (i = 0; supported[i]; i++)
+               if (lbasize == supported[i])
+                       break;
+
+       if (supported[i]) {
+               *current_lbasize = lbasize;
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+}
+
+void __nd_iostat_start(struct bio *bio, unsigned long *start)
+{
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       const int rw = bio_data_dir(bio);
+       int cpu = part_stat_lock();
+
+       *start = jiffies;
+       part_round_stats(cpu, &disk->part0);
+       part_stat_inc(cpu, &disk->part0, ios[rw]);
+       part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio));
+       part_inc_in_flight(&disk->part0, rw);
+       part_stat_unlock();
+}
+EXPORT_SYMBOL(__nd_iostat_start);
+
+void nd_iostat_end(struct bio *bio, unsigned long start)
+{
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       unsigned long duration = jiffies - start;
+       const int rw = bio_data_dir(bio);
+       int cpu = part_stat_lock();
+
+       part_stat_add(cpu, &disk->part0, ticks[rw], duration);
+       part_round_stats(cpu, &disk->part0);
+       part_dec_in_flight(&disk->part0, rw);
+       part_stat_unlock();
+}
+EXPORT_SYMBOL(nd_iostat_end);
+
 static ssize_t commands_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -321,6 +391,45 @@ void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus)
 }
 EXPORT_SYMBOL_GPL(nvdimm_bus_unregister);
 
+#ifdef CONFIG_BLK_DEV_INTEGRITY
+static int nd_pi_nop_generate_verify(struct blk_integrity_iter *iter)
+{
+       return 0;
+}
+
+int nd_integrity_init(struct gendisk *disk, unsigned long meta_size)
+{
+       struct blk_integrity integrity = {
+               .name = "ND-PI-NOP",
+               .generate_fn = nd_pi_nop_generate_verify,
+               .verify_fn = nd_pi_nop_generate_verify,
+               .tuple_size = meta_size,
+               .tag_size = meta_size,
+       };
+       int ret;
+
+       if (meta_size == 0)
+               return 0;
+
+       ret = blk_integrity_register(disk, &integrity);
+       if (ret)
+               return ret;
+
+       blk_queue_max_integrity_segments(disk->queue, 1);
+
+       return 0;
+}
+EXPORT_SYMBOL(nd_integrity_init);
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+int nd_integrity_init(struct gendisk *disk, unsigned long meta_size)
+{
+       return 0;
+}
+EXPORT_SYMBOL(nd_integrity_init);
+
+#endif
+
 static __init int libnvdimm_init(void)
 {
        int rc;