Merge branches 'pm-cpuidle', 'pm-cpufreq', 'pm-domains' and 'pm-sleep'
[deliverable/linux.git] / drivers / nvdimm / namespace_devs.c
index f981177524a19047ed08c8400a7e81f315f2785e..8ebfcaae3f5a06a4aca19611fc7c5abdeb29f16a 100644 (file)
@@ -77,6 +77,59 @@ static bool is_namespace_io(struct device *dev)
        return dev ? dev->type == &namespace_io_device_type : false;
 }
 
+static int is_uuid_busy(struct device *dev, void *data)
+{
+       u8 *uuid1 = data, *uuid2 = NULL;
+
+       if (is_namespace_pmem(dev)) {
+               struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
+
+               uuid2 = nspm->uuid;
+       } else if (is_namespace_blk(dev)) {
+               struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
+
+               uuid2 = nsblk->uuid;
+       } else if (is_nd_btt(dev)) {
+               struct nd_btt *nd_btt = to_nd_btt(dev);
+
+               uuid2 = nd_btt->uuid;
+       } else if (is_nd_pfn(dev)) {
+               struct nd_pfn *nd_pfn = to_nd_pfn(dev);
+
+               uuid2 = nd_pfn->uuid;
+       }
+
+       if (uuid2 && memcmp(uuid1, uuid2, NSLABEL_UUID_LEN) == 0)
+               return -EBUSY;
+
+       return 0;
+}
+
+static int is_namespace_uuid_busy(struct device *dev, void *data)
+{
+       if (is_nd_pmem(dev) || is_nd_blk(dev))
+               return device_for_each_child(dev, data, is_uuid_busy);
+       return 0;
+}
+
+/**
+ * nd_is_uuid_unique - verify that no other namespace has @uuid
+ * @dev: any device on a nvdimm_bus
+ * @uuid: uuid to check
+ */
+bool nd_is_uuid_unique(struct device *dev, u8 *uuid)
+{
+       struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
+
+       if (!nvdimm_bus)
+               return false;
+       WARN_ON_ONCE(!is_nvdimm_bus_locked(&nvdimm_bus->dev));
+       if (device_for_each_child(&nvdimm_bus->dev, uuid,
+                               is_namespace_uuid_busy) != 0)
+               return false;
+       return true;
+}
+
 bool pmem_should_map_pages(struct device *dev)
 {
        struct nd_region *nd_region = to_nd_region(dev->parent);
@@ -104,20 +157,10 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
        struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
        const char *suffix = NULL;
 
-       if (ndns->claim) {
-               if (is_nd_btt(ndns->claim))
-                       suffix = "s";
-               else if (is_nd_pfn(ndns->claim))
-                       suffix = "m";
-               else
-                       dev_WARN_ONCE(&ndns->dev, 1,
-                                       "unknown claim type by %s\n",
-                                       dev_name(ndns->claim));
-       }
+       if (ndns->claim && is_nd_btt(ndns->claim))
+               suffix = "s";
 
        if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev)) {
-               if (!suffix && pmem_should_map_pages(&ndns->dev))
-                       suffix = "m";
                sprintf(name, "pmem%d%s", nd_region->id, suffix ? suffix : "");
        } else if (is_namespace_blk(&ndns->dev)) {
                struct nd_namespace_blk *nsblk;
@@ -1224,6 +1267,29 @@ static ssize_t holder_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(holder);
 
+static ssize_t mode_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct nd_namespace_common *ndns = to_ndns(dev);
+       struct device *claim;
+       char *mode;
+       ssize_t rc;
+
+       device_lock(dev);
+       claim = ndns->claim;
+       if (pmem_should_map_pages(dev) || (claim && is_nd_pfn(claim)))
+               mode = "memory";
+       else if (claim && is_nd_btt(claim))
+               mode = "safe";
+       else
+               mode = "raw";
+       rc = sprintf(buf, "%s\n", mode);
+       device_unlock(dev);
+
+       return rc;
+}
+static DEVICE_ATTR_RO(mode);
+
 static ssize_t force_raw_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
 {
@@ -1247,6 +1313,7 @@ static DEVICE_ATTR_RW(force_raw);
 static struct attribute *nd_namespace_attributes[] = {
        &dev_attr_nstype.attr,
        &dev_attr_size.attr,
+       &dev_attr_mode.attr,
        &dev_attr_uuid.attr,
        &dev_attr_holder.attr,
        &dev_attr_resource.attr,
@@ -1280,7 +1347,8 @@ static umode_t namespace_visible(struct kobject *kobj,
 
        if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr
                        || a == &dev_attr_holder.attr
-                       || a == &dev_attr_force_raw.attr)
+                       || a == &dev_attr_force_raw.attr
+                       || a == &dev_attr_mode.attr)
                return a->mode;
 
        return 0;
@@ -1707,6 +1775,18 @@ void nd_region_create_blk_seed(struct nd_region *nd_region)
                nd_device_register(nd_region->ns_seed);
 }
 
+void nd_region_create_pfn_seed(struct nd_region *nd_region)
+{
+       WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
+       nd_region->pfn_seed = nd_pfn_create(nd_region);
+       /*
+        * Seed creation failures are not fatal, provisioning is simply
+        * disabled until memory becomes available
+        */
+       if (!nd_region->pfn_seed)
+               dev_err(&nd_region->dev, "failed to create pfn namespace\n");
+}
+
 void nd_region_create_btt_seed(struct nd_region *nd_region)
 {
        WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
This page took 0.027669 seconds and 5 git commands to generate.