libnvdimm, region: fix flush hint detection crash
[linux-2.6-microblaze.git] / drivers / nvdimm / region_devs.c
index 7cd705f..24abced 100644 (file)
@@ -448,6 +448,30 @@ static ssize_t read_only_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(read_only);
 
+static ssize_t nd_badblocks_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct nd_region *nd_region = to_nd_region(dev);
+
+       return badblocks_show(&nd_region->bb, buf, 0);
+}
+static struct device_attribute dev_attr_nd_badblocks = {
+       .attr = {
+               .name = "badblocks",
+               .mode = S_IRUGO
+       },
+       .show = nd_badblocks_show,
+};
+
+static ssize_t resource_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct nd_region *nd_region = to_nd_region(dev);
+
+       return sprintf(buf, "%#llx\n", nd_region->ndr_start);
+}
+static DEVICE_ATTR_RO(resource);
+
 static struct attribute *nd_region_attributes[] = {
        &dev_attr_size.attr,
        &dev_attr_nstype.attr,
@@ -460,6 +484,8 @@ static struct attribute *nd_region_attributes[] = {
        &dev_attr_available_size.attr,
        &dev_attr_namespace_seed.attr,
        &dev_attr_init_namespaces.attr,
+       &dev_attr_nd_badblocks.attr,
+       &dev_attr_resource.attr,
        NULL,
 };
 
@@ -476,6 +502,12 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
        if (!is_nd_pmem(dev) && a == &dev_attr_dax_seed.attr)
                return 0;
 
+       if (!is_nd_pmem(dev) && a == &dev_attr_nd_badblocks.attr)
+               return 0;
+
+       if (!is_nd_pmem(dev) && a == &dev_attr_resource.attr)
+               return 0;
+
        if (a != &dev_attr_set_cookie.attr
                        && a != &dev_attr_available_size.attr)
                return a->mode;
@@ -505,6 +537,15 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region)
        return 0;
 }
 
+u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
+{
+       struct nd_interleave_set *nd_set = nd_region->nd_set;
+
+       if (nd_set)
+               return nd_set->altcookie;
+       return 0;
+}
+
 void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
 {
        struct nd_label_ent *label_ent, *e;
@@ -959,17 +1000,20 @@ EXPORT_SYMBOL_GPL(nvdimm_flush);
  */
 int nvdimm_has_flush(struct nd_region *nd_region)
 {
-       struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev);
        int i;
 
        /* no nvdimm == flushing capability unknown */
        if (nd_region->ndr_mappings == 0)
                return -ENXIO;
 
-       for (i = 0; i < nd_region->ndr_mappings; i++)
-               /* flush hints present, flushing required */
-               if (ndrd_get_flush_wpq(ndrd, i, 0))
+       for (i = 0; i < nd_region->ndr_mappings; i++) {
+               struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+               struct nvdimm *nvdimm = nd_mapping->nvdimm;
+
+               /* flush hints present / available */
+               if (nvdimm->num_flush)
                        return 1;
+       }
 
        /*
         * The platform defines dimm devices without hints, assume