dax: add a sysfs knob to control memmap_on_memory behavior
[linux-2.6-microblaze.git] / drivers / dax / bus.c
index 0fd948a..27c86d0 100644 (file)
@@ -1349,6 +1349,48 @@ static ssize_t numa_node_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(numa_node);
 
+static ssize_t memmap_on_memory_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct dev_dax *dev_dax = to_dev_dax(dev);
+
+       return sysfs_emit(buf, "%d\n", dev_dax->memmap_on_memory);
+}
+
+static ssize_t memmap_on_memory_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       struct dev_dax *dev_dax = to_dev_dax(dev);
+       bool val;
+       int rc;
+
+       rc = kstrtobool(buf, &val);
+       if (rc)
+               return rc;
+
+       if (val == true && !mhp_supports_memmap_on_memory()) {
+               dev_dbg(dev, "memmap_on_memory is not available\n");
+               return -EOPNOTSUPP;
+       }
+
+       rc = down_write_killable(&dax_dev_rwsem);
+       if (rc)
+               return rc;
+
+       if (dev_dax->memmap_on_memory != val && dev->driver &&
+           to_dax_drv(dev->driver)->type == DAXDRV_KMEM_TYPE) {
+               up_write(&dax_dev_rwsem);
+               return -EBUSY;
+       }
+
+       dev_dax->memmap_on_memory = val;
+       up_write(&dax_dev_rwsem);
+
+       return len;
+}
+static DEVICE_ATTR_RW(memmap_on_memory);
+
 static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
@@ -1375,6 +1417,7 @@ static struct attribute *dev_dax_attributes[] = {
        &dev_attr_align.attr,
        &dev_attr_resource.attr,
        &dev_attr_numa_node.attr,
+       &dev_attr_memmap_on_memory.attr,
        NULL,
 };