linux/drivers/nvdimm/dimm.c
<<
>>
Prefs
   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
  24static int nvdimm_probe(struct device *dev)
  25{
  26        struct nvdimm_drvdata *ndd;
  27        int rc;
  28
  29        rc = nvdimm_check_config_data(dev);
  30        if (rc) {
  31                /* not required for non-aliased nvdimm, ex. NVDIMM-N */
  32                if (rc == -ENOTTY)
  33                        rc = 0;
  34                return rc;
  35        }
  36
  37        ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
  38        if (!ndd)
  39                return -ENOMEM;
  40
  41        dev_set_drvdata(dev, ndd);
  42        ndd->dpa.name = dev_name(dev);
  43        ndd->ns_current = -1;
  44        ndd->ns_next = -1;
  45        ndd->dpa.start = 0;
  46        ndd->dpa.end = -1;
  47        ndd->dev = dev;
  48        get_device(dev);
  49        kref_init(&ndd->kref);
  50
  51        rc = nvdimm_init_nsarea(ndd);
  52        if (rc == -EACCES)
  53                nvdimm_set_locked(dev);
  54        if (rc)
  55                goto err;
  56
  57        rc = nvdimm_init_config_data(ndd);
  58        if (rc)
  59                goto err;
  60
  61        dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
  62
  63        nvdimm_bus_lock(dev);
  64        ndd->ns_current = nd_label_validate(ndd);
  65        ndd->ns_next = nd_label_next_nsindex(ndd->ns_current);
  66        nd_label_copy(ndd, to_next_namespace_index(ndd),
  67                        to_current_namespace_index(ndd));
  68        rc = nd_label_reserve_dpa(ndd);
  69        if (ndd->ns_current >= 0)
  70                nvdimm_set_aliasing(dev);
  71        nvdimm_bus_unlock(dev);
  72
  73        if (rc)
  74                goto err;
  75
  76        return 0;
  77
  78 err:
  79        put_ndd(ndd);
  80        return rc;
  81}
  82
  83static int nvdimm_remove(struct device *dev)
  84{
  85        struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
  86
  87        if (!ndd)
  88                return 0;
  89
  90        nvdimm_bus_lock(dev);
  91        dev_set_drvdata(dev, NULL);
  92        nvdimm_bus_unlock(dev);
  93        put_ndd(ndd);
  94
  95        return 0;
  96}
  97
  98static struct nd_device_driver nvdimm_driver = {
  99        .probe = nvdimm_probe,
 100        .remove = nvdimm_remove,
 101        .drv = {
 102                .name = "nvdimm",
 103        },
 104        .type = ND_DRIVER_DIMM,
 105};
 106
 107int __init nvdimm_init(void)
 108{
 109        return nd_driver_register(&nvdimm_driver);
 110}
 111
 112void nvdimm_exit(void)
 113{
 114        driver_unregister(&nvdimm_driver.drv);
 115}
 116
 117MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DIMM);
 118