Merge tag 'libnvdimm-fixes-5.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / nvdimm / region_devs.c
index 91b5a7ade0d5ae906c682dbad47a0ae50fad447e..af30cbe7a8ea26fd5eb643af56e1a9bffaeda7ff 100644 (file)
@@ -287,7 +287,9 @@ static ssize_t deep_flush_store(struct device *dev, struct device_attribute *att
                return rc;
        if (!flush)
                return -EINVAL;
-       nvdimm_flush(nd_region);
+       rc = nvdimm_flush(nd_region, NULL);
+       if (rc)
+               return rc;
 
        return len;
 }
@@ -1081,6 +1083,11 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
        dev->of_node = ndr_desc->of_node;
        nd_region->ndr_size = resource_size(ndr_desc->res);
        nd_region->ndr_start = ndr_desc->res->start;
+       if (ndr_desc->flush)
+               nd_region->flush = ndr_desc->flush;
+       else
+               nd_region->flush = NULL;
+
        nd_device_register(dev);
 
        return nd_region;
@@ -1121,11 +1128,24 @@ struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(nvdimm_volatile_region_create);
 
+int nvdimm_flush(struct nd_region *nd_region, struct bio *bio)
+{
+       int rc = 0;
+
+       if (!nd_region->flush)
+               rc = generic_nvdimm_flush(nd_region);
+       else {
+               if (nd_region->flush(nd_region, bio))
+                       rc = -EIO;
+       }
+
+       return rc;
+}
 /**
  * nvdimm_flush - flush any posted write queues between the cpu and pmem media
  * @nd_region: blk or interleaved pmem region
  */
-void nvdimm_flush(struct nd_region *nd_region)
+int generic_nvdimm_flush(struct nd_region *nd_region)
 {
        struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev);
        int i, idx;
@@ -1149,6 +1169,8 @@ void nvdimm_flush(struct nd_region *nd_region)
                if (ndrd_get_flush_wpq(ndrd, i, 0))
                        writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));
        wmb();
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(nvdimm_flush);
 
@@ -1193,6 +1215,13 @@ int nvdimm_has_cache(struct nd_region *nd_region)
 }
 EXPORT_SYMBOL_GPL(nvdimm_has_cache);
 
+bool is_nvdimm_sync(struct nd_region *nd_region)
+{
+       return is_nd_pmem(&nd_region->dev) &&
+               !test_bit(ND_REGION_ASYNC, &nd_region->flags);
+}
+EXPORT_SYMBOL_GPL(is_nvdimm_sync);
+
 struct conflict_context {
        struct nd_region *nd_region;
        resource_size_t start, size;