Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
0004  */
0005 #include <linux/device.h>
0006 #include <linux/sizes.h>
0007 #include <linux/slab.h>
0008 #include <linux/mm.h>
0009 #include "nd-core.h"
0010 #include "pfn.h"
0011 #include "nd.h"
0012 
0013 static void nd_dax_release(struct device *dev)
0014 {
0015     struct nd_region *nd_region = to_nd_region(dev->parent);
0016     struct nd_dax *nd_dax = to_nd_dax(dev);
0017     struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
0018 
0019     dev_dbg(dev, "trace\n");
0020     nd_detach_ndns(dev, &nd_pfn->ndns);
0021     ida_simple_remove(&nd_region->dax_ida, nd_pfn->id);
0022     kfree(nd_pfn->uuid);
0023     kfree(nd_dax);
0024 }
0025 
0026 struct nd_dax *to_nd_dax(struct device *dev)
0027 {
0028     struct nd_dax *nd_dax = container_of(dev, struct nd_dax, nd_pfn.dev);
0029 
0030     WARN_ON(!is_nd_dax(dev));
0031     return nd_dax;
0032 }
0033 EXPORT_SYMBOL(to_nd_dax);
0034 
0035 static const struct device_type nd_dax_device_type = {
0036     .name = "nd_dax",
0037     .release = nd_dax_release,
0038     .groups = nd_pfn_attribute_groups,
0039 };
0040 
0041 bool is_nd_dax(struct device *dev)
0042 {
0043     return dev ? dev->type == &nd_dax_device_type : false;
0044 }
0045 EXPORT_SYMBOL(is_nd_dax);
0046 
0047 static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
0048 {
0049     struct nd_pfn *nd_pfn;
0050     struct nd_dax *nd_dax;
0051     struct device *dev;
0052 
0053     nd_dax = kzalloc(sizeof(*nd_dax), GFP_KERNEL);
0054     if (!nd_dax)
0055         return NULL;
0056 
0057     nd_pfn = &nd_dax->nd_pfn;
0058     nd_pfn->id = ida_simple_get(&nd_region->dax_ida, 0, 0, GFP_KERNEL);
0059     if (nd_pfn->id < 0) {
0060         kfree(nd_dax);
0061         return NULL;
0062     }
0063 
0064     dev = &nd_pfn->dev;
0065     dev_set_name(dev, "dax%d.%d", nd_region->id, nd_pfn->id);
0066     dev->type = &nd_dax_device_type;
0067     dev->parent = &nd_region->dev;
0068 
0069     return nd_dax;
0070 }
0071 
0072 struct device *nd_dax_create(struct nd_region *nd_region)
0073 {
0074     struct device *dev = NULL;
0075     struct nd_dax *nd_dax;
0076 
0077     if (!is_memory(&nd_region->dev))
0078         return NULL;
0079 
0080     nd_dax = nd_dax_alloc(nd_region);
0081     if (nd_dax)
0082         dev = nd_pfn_devinit(&nd_dax->nd_pfn, NULL);
0083     nd_device_register(dev);
0084     return dev;
0085 }
0086 
0087 int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
0088 {
0089     int rc;
0090     struct nd_dax *nd_dax;
0091     struct device *dax_dev;
0092     struct nd_pfn *nd_pfn;
0093     struct nd_pfn_sb *pfn_sb;
0094     struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
0095 
0096     if (ndns->force_raw)
0097         return -ENODEV;
0098 
0099     switch (ndns->claim_class) {
0100     case NVDIMM_CCLASS_NONE:
0101     case NVDIMM_CCLASS_DAX:
0102         break;
0103     default:
0104         return -ENODEV;
0105     }
0106 
0107     nvdimm_bus_lock(&ndns->dev);
0108     nd_dax = nd_dax_alloc(nd_region);
0109     nd_pfn = &nd_dax->nd_pfn;
0110     dax_dev = nd_pfn_devinit(nd_pfn, ndns);
0111     nvdimm_bus_unlock(&ndns->dev);
0112     if (!dax_dev)
0113         return -ENOMEM;
0114     pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
0115     nd_pfn->pfn_sb = pfn_sb;
0116     rc = nd_pfn_validate(nd_pfn, DAX_SIG);
0117     dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>");
0118     if (rc < 0) {
0119         nd_detach_ndns(dax_dev, &nd_pfn->ndns);
0120         put_device(dax_dev);
0121     } else
0122         nd_device_register(dax_dev);
0123 
0124     return rc;
0125 }
0126 EXPORT_SYMBOL(nd_dax_probe);