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.c363
1 files changed, 85 insertions, 278 deletions
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 948806e57cee..e428468ab661 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -1,15 +1,6 @@
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 * 3#include <linux/memremap.h>
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> 4#include <linux/pagemap.h>
14#include <linux/module.h> 5#include <linux/module.h>
15#include <linux/device.h> 6#include <linux/device.h>
@@ -21,161 +12,39 @@
21#include <linux/mm.h> 12#include <linux/mm.h>
22#include <linux/mman.h> 13#include <linux/mman.h>
23#include "dax-private.h" 14#include "dax-private.h"
24#include "dax.h" 15#include "bus.h"
25 16
26static struct class *dax_class; 17static struct dev_dax *ref_to_dev_dax(struct percpu_ref *ref)
27
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{ 18{
89 kref_put(&dax_region->kref, dax_region_free); 19 return container_of(ref, struct dev_dax, ref);
90} 20}
91EXPORT_SYMBOL_GPL(dax_region_put);
92 21
93static void dax_region_unregister(void *region) 22static void dev_dax_percpu_release(struct percpu_ref *ref)
94{ 23{
95 struct dax_region *dax_region = region; 24 struct dev_dax *dev_dax = ref_to_dev_dax(ref);
96 25
97 sysfs_remove_groups(&dax_region->dev->kobj, 26 dev_dbg(&dev_dax->dev, "%s\n", __func__);
98 dax_region_attribute_groups); 27 complete(&dev_dax->cmp);
99 dax_region_put(dax_region);
100} 28}
101 29
102struct dax_region *alloc_dax_region(struct device *parent, int region_id, 30static void dev_dax_percpu_exit(void *data)
103 struct resource *res, unsigned int align, void *addr,
104 unsigned long pfn_flags)
105{ 31{
106 struct dax_region *dax_region; 32 struct percpu_ref *ref = data;
107 33 struct dev_dax *dev_dax = ref_to_dev_dax(ref);
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 ida_init(&dax_region->ida);
132 dax_region->align = align;
133 dax_region->dev = parent;
134 dax_region->base = addr;
135 if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
136 kfree(dax_region);
137 return NULL;
138 }
139 34
140 kref_get(&dax_region->kref); 35 dev_dbg(&dev_dax->dev, "%s\n", __func__);
141 if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) 36 wait_for_completion(&dev_dax->cmp);
142 return NULL; 37 percpu_ref_exit(ref);
143 return dax_region;
144} 38}
145EXPORT_SYMBOL_GPL(alloc_dax_region);
146 39
147static struct dev_dax *to_dev_dax(struct device *dev) 40static void dev_dax_percpu_kill(struct percpu_ref *data)
148{ 41{
149 return container_of(dev, struct dev_dax, dev); 42 struct percpu_ref *ref = data;
150} 43 struct dev_dax *dev_dax = ref_to_dev_dax(ref);
151
152static ssize_t size_show(struct device *dev,
153 struct device_attribute *attr, char *buf)
154{
155 struct dev_dax *dev_dax = to_dev_dax(dev);
156 unsigned long long size = 0;
157 int i;
158 44
159 for (i = 0; i < dev_dax->num_resources; i++) 45 dev_dbg(&dev_dax->dev, "%s\n", __func__);
160 size += resource_size(&dev_dax->res[i]); 46 percpu_ref_kill(ref);
161
162 return sprintf(buf, "%llu\n", size);
163} 47}
164static DEVICE_ATTR_RO(size);
165
166static struct attribute *dev_dax_attributes[] = {
167 &dev_attr_size.attr,
168 NULL,
169};
170
171static const struct attribute_group dev_dax_attribute_group = {
172 .attrs = dev_dax_attributes,
173};
174
175static const struct attribute_group *dax_attribute_groups[] = {
176 &dev_dax_attribute_group,
177 NULL,
178};
179 48
180static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma, 49static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
181 const char *func) 50 const char *func)
@@ -226,21 +95,11 @@ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
226__weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff, 95__weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
227 unsigned long size) 96 unsigned long size)
228{ 97{
229 struct resource *res; 98 struct resource *res = &dev_dax->region->res;
230 /* gcc-4.6.3-nolibc for i386 complains that this is uninitialized */ 99 phys_addr_t phys;
231 phys_addr_t uninitialized_var(phys);
232 int i;
233
234 for (i = 0; i < dev_dax->num_resources; i++) {
235 res = &dev_dax->res[i];
236 phys = pgoff * PAGE_SIZE + res->start;
237 if (phys >= res->start && phys <= res->end)
238 break;
239 pgoff -= PHYS_PFN(resource_size(res));
240 }
241 100
242 if (i < dev_dax->num_resources) { 101 phys = pgoff * PAGE_SIZE + res->start;
243 res = &dev_dax->res[i]; 102 if (phys >= res->start && phys <= res->end) {
244 if (phys + size - 1 <= res->end) 103 if (phys + size - 1 <= res->end)
245 return phys; 104 return phys;
246 } 105 }
@@ -576,152 +435,100 @@ static const struct file_operations dax_fops = {
576 .mmap_supported_flags = MAP_SYNC, 435 .mmap_supported_flags = MAP_SYNC,
577}; 436};
578 437
579static void dev_dax_release(struct device *dev) 438static void dev_dax_cdev_del(void *cdev)
580{ 439{
581 struct dev_dax *dev_dax = to_dev_dax(dev); 440 cdev_del(cdev);
582 struct dax_region *dax_region = dev_dax->region;
583 struct dax_device *dax_dev = dev_dax->dax_dev;
584
585 if (dev_dax->id >= 0)
586 ida_simple_remove(&dax_region->ida, dev_dax->id);
587 dax_region_put(dax_region);
588 put_dax(dax_dev);
589 kfree(dev_dax);
590} 441}
591 442
592static void kill_dev_dax(struct dev_dax *dev_dax) 443static void dev_dax_kill(void *dev_dax)
593{ 444{
594 struct dax_device *dax_dev = dev_dax->dax_dev; 445 kill_dev_dax(dev_dax);
595 struct inode *inode = dax_inode(dax_dev);
596
597 kill_dax(dax_dev);
598 unmap_mapping_range(inode->i_mapping, 0, 0, 1);
599} 446}
600 447
601static void unregister_dev_dax(void *dev) 448int dev_dax_probe(struct device *dev)
602{ 449{
603 struct dev_dax *dev_dax = to_dev_dax(dev); 450 struct dev_dax *dev_dax = to_dev_dax(dev);
604 struct dax_device *dax_dev = dev_dax->dax_dev; 451 struct dax_device *dax_dev = dev_dax->dax_dev;
605 struct inode *inode = dax_inode(dax_dev); 452 struct resource *res = &dev_dax->region->res;
606 struct cdev *cdev = inode->i_cdev;
607
608 dev_dbg(dev, "trace\n");
609
610 kill_dev_dax(dev_dax);
611 cdev_device_del(cdev, dev);
612 put_device(dev);
613}
614
615struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
616 int id, struct resource *res, int count)
617{
618 struct device *parent = dax_region->dev;
619 struct dax_device *dax_dev;
620 struct dev_dax *dev_dax;
621 struct inode *inode; 453 struct inode *inode;
622 struct device *dev;
623 struct cdev *cdev; 454 struct cdev *cdev;
624 int rc, i; 455 void *addr;
625 456 int rc;
626 if (!count) 457
627 return ERR_PTR(-EINVAL); 458 /* 1:1 map region resource range to device-dax instance range */
628 459 if (!devm_request_mem_region(dev, res->start, resource_size(res),
629 dev_dax = kzalloc(struct_size(dev_dax, res, count), GFP_KERNEL); 460 dev_name(dev))) {
630 if (!dev_dax) 461 dev_warn(dev, "could not reserve region %pR\n", res);
631 return ERR_PTR(-ENOMEM); 462 return -EBUSY;
632
633 for (i = 0; i < count; i++) {
634 if (!IS_ALIGNED(res[i].start, dax_region->align)
635 || !IS_ALIGNED(resource_size(&res[i]),
636 dax_region->align)) {
637 rc = -EINVAL;
638 break;
639 }
640 dev_dax->res[i].start = res[i].start;
641 dev_dax->res[i].end = res[i].end;
642 } 463 }
643 464
644 if (i < count) 465 init_completion(&dev_dax->cmp);
645 goto err_id; 466 rc = percpu_ref_init(&dev_dax->ref, dev_dax_percpu_release, 0,
467 GFP_KERNEL);
468 if (rc)
469 return rc;
646 470
647 if (id < 0) { 471 rc = devm_add_action_or_reset(dev, dev_dax_percpu_exit, &dev_dax->ref);
648 id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL); 472 if (rc)
649 dev_dax->id = id; 473 return rc;
650 if (id < 0) {
651 rc = id;
652 goto err_id;
653 }
654 } else {
655 /* region provider owns @id lifetime */
656 dev_dax->id = -1;
657 }
658 474
659 /* 475 dev_dax->pgmap.ref = &dev_dax->ref;
660 * No 'host' or dax_operations since there is no access to this 476 dev_dax->pgmap.kill = dev_dax_percpu_kill;
661 * device outside of mmap of the resulting character device. 477 addr = devm_memremap_pages(dev, &dev_dax->pgmap);
662 */ 478 if (IS_ERR(addr)) {
663 dax_dev = alloc_dax(dev_dax, NULL, NULL); 479 devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref);
664 if (!dax_dev) { 480 percpu_ref_exit(&dev_dax->ref);
665 rc = -ENOMEM; 481 return PTR_ERR(addr);
666 goto err_dax;
667 } 482 }
668 483
669 /* from here on we're committed to teardown via dax_dev_release() */
670 dev = &dev_dax->dev;
671 device_initialize(dev);
672
673 inode = dax_inode(dax_dev); 484 inode = dax_inode(dax_dev);
674 cdev = inode->i_cdev; 485 cdev = inode->i_cdev;
675 cdev_init(cdev, &dax_fops); 486 cdev_init(cdev, &dax_fops);
676 cdev->owner = parent->driver->owner; 487 if (dev->class) {
677 488 /* for the CONFIG_DEV_DAX_PMEM_COMPAT case */
678 dev_dax->num_resources = count; 489 cdev->owner = dev->parent->driver->owner;
679 dev_dax->dax_dev = dax_dev; 490 } else
680 dev_dax->region = dax_region; 491 cdev->owner = dev->driver->owner;
681 kref_get(&dax_region->kref); 492 cdev_set_parent(cdev, &dev->kobj);
682 493 rc = cdev_add(cdev, dev->devt, 1);
683 dev->devt = inode->i_rdev;
684 dev->class = dax_class;
685 dev->parent = parent;
686 dev->groups = dax_attribute_groups;
687 dev->release = dev_dax_release;
688 dev_set_name(dev, "dax%d.%d", dax_region->id, id);
689
690 rc = cdev_device_add(cdev, dev);
691 if (rc) {
692 kill_dev_dax(dev_dax);
693 put_device(dev);
694 return ERR_PTR(rc);
695 }
696
697 rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev);
698 if (rc) 494 if (rc)
699 return ERR_PTR(rc); 495 return rc;
700 496
701 return dev_dax; 497 rc = devm_add_action_or_reset(dev, dev_dax_cdev_del, cdev);
498 if (rc)
499 return rc;
702 500
703 err_dax: 501 run_dax(dax_dev);
704 if (dev_dax->id >= 0) 502 return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
705 ida_simple_remove(&dax_region->ida, dev_dax->id); 503}
706 err_id: 504EXPORT_SYMBOL_GPL(dev_dax_probe);
707 kfree(dev_dax);
708 505
709 return ERR_PTR(rc); 506static int dev_dax_remove(struct device *dev)
507{
508 /* all probe actions are unwound by devm */
509 return 0;
710} 510}
711EXPORT_SYMBOL_GPL(devm_create_dev_dax); 511
512static struct dax_device_driver device_dax_driver = {
513 .drv = {
514 .probe = dev_dax_probe,
515 .remove = dev_dax_remove,
516 },
517 .match_always = 1,
518};
712 519
713static int __init dax_init(void) 520static int __init dax_init(void)
714{ 521{
715 dax_class = class_create(THIS_MODULE, "dax"); 522 return dax_driver_register(&device_dax_driver);
716 return PTR_ERR_OR_ZERO(dax_class);
717} 523}
718 524
719static void __exit dax_exit(void) 525static void __exit dax_exit(void)
720{ 526{
721 class_destroy(dax_class); 527 dax_driver_unregister(&device_dax_driver);
722} 528}
723 529
724MODULE_AUTHOR("Intel Corporation"); 530MODULE_AUTHOR("Intel Corporation");
725MODULE_LICENSE("GPL v2"); 531MODULE_LICENSE("GPL v2");
726subsys_initcall(dax_init); 532module_init(dax_init);
727module_exit(dax_exit); 533module_exit(dax_exit);
534MODULE_ALIAS_DAX_DEVICE(0);