1 /* 2 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 */ 13 #include <linux/vmalloc.h> 14 #include <linux/module.h> 15 #include <linux/device.h> 16 #include <linux/sizes.h> 17 #include <linux/ndctl.h> 18 #include <linux/slab.h> 19 #include <linux/mm.h> 20 #include <linux/nd.h> 21 #include "label.h" 22 #include "nd.h" 23 24 static int nvdimm_probe(struct device *dev) 25 { 26 struct nvdimm_drvdata *ndd; 27 int rc; 28 29 ndd = kzalloc(sizeof(*ndd), GFP_KERNEL); 30 if (!ndd) 31 return -ENOMEM; 32 33 dev_set_drvdata(dev, ndd); 34 ndd->dpa.name = dev_name(dev); 35 ndd->ns_current = -1; 36 ndd->ns_next = -1; 37 ndd->dpa.start = 0; 38 ndd->dpa.end = -1; 39 ndd->dev = dev; 40 get_device(dev); 41 kref_init(&ndd->kref); 42 43 rc = nvdimm_init_nsarea(ndd); 44 if (rc) 45 goto err; 46 47 rc = nvdimm_init_config_data(ndd); 48 if (rc) 49 goto err; 50 51 dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size); 52 53 nvdimm_bus_lock(dev); 54 ndd->ns_current = nd_label_validate(ndd); 55 ndd->ns_next = nd_label_next_nsindex(ndd->ns_current); 56 nd_label_copy(ndd, to_next_namespace_index(ndd), 57 to_current_namespace_index(ndd)); 58 rc = nd_label_reserve_dpa(ndd); 59 nvdimm_bus_unlock(dev); 60 61 if (rc) 62 goto err; 63 64 return 0; 65 66 err: 67 put_ndd(ndd); 68 return rc; 69 } 70 71 static int nvdimm_remove(struct device *dev) 72 { 73 struct nvdimm_drvdata *ndd = dev_get_drvdata(dev); 74 75 nvdimm_bus_lock(dev); 76 dev_set_drvdata(dev, NULL); 77 nvdimm_bus_unlock(dev); 78 put_ndd(ndd); 79 80 return 0; 81 } 82 83 static struct nd_device_driver nvdimm_driver = { 84 .probe = nvdimm_probe, 85 .remove = nvdimm_remove, 86 .drv = { 87 .name = "nvdimm", 88 }, 89 .type = ND_DRIVER_DIMM, 90 }; 91 92 int __init nvdimm_init(void) 93 { 94 return nd_driver_register(&nvdimm_driver); 95 } 96 97 void nvdimm_exit(void) 98 { 99 driver_unregister(&nvdimm_driver.drv); 100 } 101 102 MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DIMM); 103