aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dax/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dax/device.c')
-rw-r--r--drivers/dax/device.c185
1 files changed, 3 insertions, 182 deletions
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index db12e24b8005..1fc375783e0b 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -1,15 +1,5 @@
1/* 1// SPDX-License-Identifier: GPL-2.0
2 * Copyright(c) 2016 - 2017 Intel Corporation. All rights reserved. 2/* Copyright(c) 2016-2018 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/pagemap.h> 3#include <linux/pagemap.h>
14#include <linux/module.h> 4#include <linux/module.h>
15#include <linux/device.h> 5#include <linux/device.h>
@@ -21,156 +11,10 @@
21#include <linux/mm.h> 11#include <linux/mm.h>
22#include <linux/mman.h> 12#include <linux/mman.h>
23#include "dax-private.h" 13#include "dax-private.h"
24#include "dax.h" 14#include "bus.h"
25 15
26static struct class *dax_class; 16static struct class *dax_class;
27 17
28/*
29 * Rely on the fact that drvdata is set before the attributes are
30 * registered, and that the attributes are unregistered before drvdata
31 * is cleared to assume that drvdata is always valid.
32 */
33static ssize_t id_show(struct device *dev,
34 struct device_attribute *attr, char *buf)
35{
36 struct dax_region *dax_region = dev_get_drvdata(dev);
37
38 return sprintf(buf, "%d\n", dax_region->id);
39}
40static DEVICE_ATTR_RO(id);
41
42static ssize_t region_size_show(struct device *dev,
43 struct device_attribute *attr, char *buf)
44{
45 struct dax_region *dax_region = dev_get_drvdata(dev);
46
47 return sprintf(buf, "%llu\n", (unsigned long long)
48 resource_size(&dax_region->res));
49}
50static struct device_attribute dev_attr_region_size = __ATTR(size, 0444,
51 region_size_show, NULL);
52
53static ssize_t align_show(struct device *dev,
54 struct device_attribute *attr, char *buf)
55{
56 struct dax_region *dax_region = dev_get_drvdata(dev);
57
58 return sprintf(buf, "%u\n", dax_region->align);
59}
60static DEVICE_ATTR_RO(align);
61
62static struct attribute *dax_region_attributes[] = {
63 &dev_attr_region_size.attr,
64 &dev_attr_align.attr,
65 &dev_attr_id.attr,
66 NULL,
67};
68
69static const struct attribute_group dax_region_attribute_group = {
70 .name = "dax_region",
71 .attrs = dax_region_attributes,
72};
73
74static const struct attribute_group *dax_region_attribute_groups[] = {
75 &dax_region_attribute_group,
76 NULL,
77};
78
79static void dax_region_free(struct kref *kref)
80{
81 struct dax_region *dax_region;
82
83 dax_region = container_of(kref, struct dax_region, kref);
84 kfree(dax_region);
85}
86
87void dax_region_put(struct dax_region *dax_region)
88{
89 kref_put(&dax_region->kref, dax_region_free);
90}
91EXPORT_SYMBOL_GPL(dax_region_put);
92
93static void dax_region_unregister(void *region)
94{
95 struct dax_region *dax_region = region;
96
97 sysfs_remove_groups(&dax_region->dev->kobj,
98 dax_region_attribute_groups);
99 dax_region_put(dax_region);
100}
101
102struct dax_region *alloc_dax_region(struct device *parent, int region_id,
103 struct resource *res, unsigned int align,
104 unsigned long pfn_flags)
105{
106 struct dax_region *dax_region;
107
108 /*
109 * The DAX core assumes that it can store its private data in
110 * parent->driver_data. This WARN is a reminder / safeguard for
111 * developers of device-dax drivers.
112 */
113 if (dev_get_drvdata(parent)) {
114 dev_WARN(parent, "dax core failed to setup private data\n");
115 return NULL;
116 }
117
118 if (!IS_ALIGNED(res->start, align)
119 || !IS_ALIGNED(resource_size(res), align))
120 return NULL;
121
122 dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL);
123 if (!dax_region)
124 return NULL;
125
126 dev_set_drvdata(parent, dax_region);
127 memcpy(&dax_region->res, res, sizeof(*res));
128 dax_region->pfn_flags = pfn_flags;
129 kref_init(&dax_region->kref);
130 dax_region->id = region_id;
131 dax_region->align = align;
132 dax_region->dev = parent;
133 if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
134 kfree(dax_region);
135 return NULL;
136 }
137
138 kref_get(&dax_region->kref);
139 if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
140 return NULL;
141 return dax_region;
142}
143EXPORT_SYMBOL_GPL(alloc_dax_region);
144
145static struct dev_dax *to_dev_dax(struct device *dev)
146{
147 return container_of(dev, struct dev_dax, dev);
148}
149
150static ssize_t size_show(struct device *dev,
151 struct device_attribute *attr, char *buf)
152{
153 struct dev_dax *dev_dax = to_dev_dax(dev);
154 unsigned long long size = resource_size(&dev_dax->region->res);
155
156 return sprintf(buf, "%llu\n", size);
157}
158static DEVICE_ATTR_RO(size);
159
160static struct attribute *dev_dax_attributes[] = {
161 &dev_attr_size.attr,
162 NULL,
163};
164
165static const struct attribute_group dev_dax_attribute_group = {
166 .attrs = dev_dax_attributes,
167};
168
169static const struct attribute_group *dax_attribute_groups[] = {
170 &dev_dax_attribute_group,
171 NULL,
172};
173
174static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, 18static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
175 const char *func) 19 const char *func)
176{ 20{
@@ -571,29 +415,6 @@ static void dev_dax_release(struct device *dev)
571 kfree(dev_dax); 415 kfree(dev_dax);
572} 416}
573 417
574static void kill_dev_dax(struct dev_dax *dev_dax)
575{
576 struct dax_device *dax_dev = dev_dax->dax_dev;
577 struct inode *inode = dax_inode(dax_dev);
578
579 kill_dax(dax_dev);
580 unmap_mapping_range(inode->i_mapping, 0, 0, 1);
581}
582
583static void unregister_dev_dax(void *dev)
584{
585 struct dev_dax *dev_dax = to_dev_dax(dev);
586 struct dax_device *dax_dev = dev_dax->dax_dev;
587 struct inode *inode = dax_inode(dax_dev);
588 struct cdev *cdev = inode->i_cdev;
589
590 dev_dbg(dev, "trace\n");
591
592 kill_dev_dax(dev_dax);
593 cdev_device_del(cdev, dev);
594 put_device(dev);
595}
596
597struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id) 418struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
598{ 419{
599 struct device *parent = dax_region->dev; 420 struct device *parent = dax_region->dev;