1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 2016-2018 Intel Corporation. All rights reserved. */
3*4882a593Smuzhiyun #include <linux/memremap.h>
4*4882a593Smuzhiyun #include <linux/pagemap.h>
5*4882a593Smuzhiyun #include <linux/module.h>
6*4882a593Smuzhiyun #include <linux/device.h>
7*4882a593Smuzhiyun #include <linux/pfn_t.h>
8*4882a593Smuzhiyun #include <linux/cdev.h>
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/dax.h>
11*4882a593Smuzhiyun #include <linux/fs.h>
12*4882a593Smuzhiyun #include <linux/mm.h>
13*4882a593Smuzhiyun #include <linux/mman.h>
14*4882a593Smuzhiyun #include "dax-private.h"
15*4882a593Smuzhiyun #include "bus.h"
16*4882a593Smuzhiyun
check_vma(struct dev_dax * dev_dax,struct vm_area_struct * vma,const char * func)17*4882a593Smuzhiyun static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
18*4882a593Smuzhiyun const char *func)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun struct device *dev = &dev_dax->dev;
21*4882a593Smuzhiyun unsigned long mask;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun if (!dax_alive(dev_dax->dax_dev))
24*4882a593Smuzhiyun return -ENXIO;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* prevent private mappings from being established */
27*4882a593Smuzhiyun if ((vma->vm_flags & VM_MAYSHARE) != VM_MAYSHARE) {
28*4882a593Smuzhiyun dev_info_ratelimited(dev,
29*4882a593Smuzhiyun "%s: %s: fail, attempted private mapping\n",
30*4882a593Smuzhiyun current->comm, func);
31*4882a593Smuzhiyun return -EINVAL;
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun mask = dev_dax->align - 1;
35*4882a593Smuzhiyun if (vma->vm_start & mask || vma->vm_end & mask) {
36*4882a593Smuzhiyun dev_info_ratelimited(dev,
37*4882a593Smuzhiyun "%s: %s: fail, unaligned vma (%#lx - %#lx, %#lx)\n",
38*4882a593Smuzhiyun current->comm, func, vma->vm_start, vma->vm_end,
39*4882a593Smuzhiyun mask);
40*4882a593Smuzhiyun return -EINVAL;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (!vma_is_dax(vma)) {
44*4882a593Smuzhiyun dev_info_ratelimited(dev,
45*4882a593Smuzhiyun "%s: %s: fail, vma is not DAX capable\n",
46*4882a593Smuzhiyun current->comm, func);
47*4882a593Smuzhiyun return -EINVAL;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun return 0;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* see "strong" declaration in tools/testing/nvdimm/dax-dev.c */
dax_pgoff_to_phys(struct dev_dax * dev_dax,pgoff_t pgoff,unsigned long size)54*4882a593Smuzhiyun __weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
55*4882a593Smuzhiyun unsigned long size)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun int i;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun for (i = 0; i < dev_dax->nr_range; i++) {
60*4882a593Smuzhiyun struct dev_dax_range *dax_range = &dev_dax->ranges[i];
61*4882a593Smuzhiyun struct range *range = &dax_range->range;
62*4882a593Smuzhiyun unsigned long long pgoff_end;
63*4882a593Smuzhiyun phys_addr_t phys;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun pgoff_end = dax_range->pgoff + PHYS_PFN(range_len(range)) - 1;
66*4882a593Smuzhiyun if (pgoff < dax_range->pgoff || pgoff > pgoff_end)
67*4882a593Smuzhiyun continue;
68*4882a593Smuzhiyun phys = PFN_PHYS(pgoff - dax_range->pgoff) + range->start;
69*4882a593Smuzhiyun if (phys + size - 1 <= range->end)
70*4882a593Smuzhiyun return phys;
71*4882a593Smuzhiyun break;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun return -1;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
__dev_dax_pte_fault(struct dev_dax * dev_dax,struct vm_fault * vmf,pfn_t * pfn)76*4882a593Smuzhiyun static vm_fault_t __dev_dax_pte_fault(struct dev_dax *dev_dax,
77*4882a593Smuzhiyun struct vm_fault *vmf, pfn_t *pfn)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct device *dev = &dev_dax->dev;
80*4882a593Smuzhiyun phys_addr_t phys;
81*4882a593Smuzhiyun unsigned int fault_size = PAGE_SIZE;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun if (check_vma(dev_dax, vmf->vma, __func__))
84*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (dev_dax->align > PAGE_SIZE) {
87*4882a593Smuzhiyun dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
88*4882a593Smuzhiyun dev_dax->align, fault_size);
89*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (fault_size != dev_dax->align)
93*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun phys = dax_pgoff_to_phys(dev_dax, vmf->pgoff, PAGE_SIZE);
96*4882a593Smuzhiyun if (phys == -1) {
97*4882a593Smuzhiyun dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", vmf->pgoff);
98*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun *pfn = phys_to_pfn_t(phys, PFN_DEV|PFN_MAP);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return vmf_insert_mixed(vmf->vma, vmf->address, *pfn);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
__dev_dax_pmd_fault(struct dev_dax * dev_dax,struct vm_fault * vmf,pfn_t * pfn)106*4882a593Smuzhiyun static vm_fault_t __dev_dax_pmd_fault(struct dev_dax *dev_dax,
107*4882a593Smuzhiyun struct vm_fault *vmf, pfn_t *pfn)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun unsigned long pmd_addr = vmf->address & PMD_MASK;
110*4882a593Smuzhiyun struct device *dev = &dev_dax->dev;
111*4882a593Smuzhiyun phys_addr_t phys;
112*4882a593Smuzhiyun pgoff_t pgoff;
113*4882a593Smuzhiyun unsigned int fault_size = PMD_SIZE;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (check_vma(dev_dax, vmf->vma, __func__))
116*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (dev_dax->align > PMD_SIZE) {
119*4882a593Smuzhiyun dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
120*4882a593Smuzhiyun dev_dax->align, fault_size);
121*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun if (fault_size < dev_dax->align)
125*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
126*4882a593Smuzhiyun else if (fault_size > dev_dax->align)
127*4882a593Smuzhiyun return VM_FAULT_FALLBACK;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /* if we are outside of the VMA */
130*4882a593Smuzhiyun if (pmd_addr < vmf->vma->vm_start ||
131*4882a593Smuzhiyun (pmd_addr + PMD_SIZE) > vmf->vma->vm_end)
132*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun pgoff = linear_page_index(vmf->vma, pmd_addr);
135*4882a593Smuzhiyun phys = dax_pgoff_to_phys(dev_dax, pgoff, PMD_SIZE);
136*4882a593Smuzhiyun if (phys == -1) {
137*4882a593Smuzhiyun dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", pgoff);
138*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun *pfn = phys_to_pfn_t(phys, PFN_DEV|PFN_MAP);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return vmf_insert_pfn_pmd(vmf, *pfn, vmf->flags & FAULT_FLAG_WRITE);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
__dev_dax_pud_fault(struct dev_dax * dev_dax,struct vm_fault * vmf,pfn_t * pfn)147*4882a593Smuzhiyun static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
148*4882a593Smuzhiyun struct vm_fault *vmf, pfn_t *pfn)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun unsigned long pud_addr = vmf->address & PUD_MASK;
151*4882a593Smuzhiyun struct device *dev = &dev_dax->dev;
152*4882a593Smuzhiyun phys_addr_t phys;
153*4882a593Smuzhiyun pgoff_t pgoff;
154*4882a593Smuzhiyun unsigned int fault_size = PUD_SIZE;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (check_vma(dev_dax, vmf->vma, __func__))
158*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (dev_dax->align > PUD_SIZE) {
161*4882a593Smuzhiyun dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
162*4882a593Smuzhiyun dev_dax->align, fault_size);
163*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun if (fault_size < dev_dax->align)
167*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
168*4882a593Smuzhiyun else if (fault_size > dev_dax->align)
169*4882a593Smuzhiyun return VM_FAULT_FALLBACK;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /* if we are outside of the VMA */
172*4882a593Smuzhiyun if (pud_addr < vmf->vma->vm_start ||
173*4882a593Smuzhiyun (pud_addr + PUD_SIZE) > vmf->vma->vm_end)
174*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun pgoff = linear_page_index(vmf->vma, pud_addr);
177*4882a593Smuzhiyun phys = dax_pgoff_to_phys(dev_dax, pgoff, PUD_SIZE);
178*4882a593Smuzhiyun if (phys == -1) {
179*4882a593Smuzhiyun dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", pgoff);
180*4882a593Smuzhiyun return VM_FAULT_SIGBUS;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun *pfn = phys_to_pfn_t(phys, PFN_DEV|PFN_MAP);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun return vmf_insert_pfn_pud(vmf, *pfn, vmf->flags & FAULT_FLAG_WRITE);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun #else
__dev_dax_pud_fault(struct dev_dax * dev_dax,struct vm_fault * vmf,pfn_t * pfn)188*4882a593Smuzhiyun static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
189*4882a593Smuzhiyun struct vm_fault *vmf, pfn_t *pfn)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun return VM_FAULT_FALLBACK;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun #endif /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
194*4882a593Smuzhiyun
dev_dax_huge_fault(struct vm_fault * vmf,enum page_entry_size pe_size)195*4882a593Smuzhiyun static vm_fault_t dev_dax_huge_fault(struct vm_fault *vmf,
196*4882a593Smuzhiyun enum page_entry_size pe_size)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct file *filp = vmf->vma->vm_file;
199*4882a593Smuzhiyun unsigned long fault_size;
200*4882a593Smuzhiyun vm_fault_t rc = VM_FAULT_SIGBUS;
201*4882a593Smuzhiyun int id;
202*4882a593Smuzhiyun pfn_t pfn;
203*4882a593Smuzhiyun struct dev_dax *dev_dax = filp->private_data;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun dev_dbg(&dev_dax->dev, "%s: %s (%#lx - %#lx) size = %d\n", current->comm,
206*4882a593Smuzhiyun (vmf->flags & FAULT_FLAG_WRITE) ? "write" : "read",
207*4882a593Smuzhiyun vmf->vma->vm_start, vmf->vma->vm_end, pe_size);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun id = dax_read_lock();
210*4882a593Smuzhiyun switch (pe_size) {
211*4882a593Smuzhiyun case PE_SIZE_PTE:
212*4882a593Smuzhiyun fault_size = PAGE_SIZE;
213*4882a593Smuzhiyun rc = __dev_dax_pte_fault(dev_dax, vmf, &pfn);
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun case PE_SIZE_PMD:
216*4882a593Smuzhiyun fault_size = PMD_SIZE;
217*4882a593Smuzhiyun rc = __dev_dax_pmd_fault(dev_dax, vmf, &pfn);
218*4882a593Smuzhiyun break;
219*4882a593Smuzhiyun case PE_SIZE_PUD:
220*4882a593Smuzhiyun fault_size = PUD_SIZE;
221*4882a593Smuzhiyun rc = __dev_dax_pud_fault(dev_dax, vmf, &pfn);
222*4882a593Smuzhiyun break;
223*4882a593Smuzhiyun default:
224*4882a593Smuzhiyun rc = VM_FAULT_SIGBUS;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (rc == VM_FAULT_NOPAGE) {
228*4882a593Smuzhiyun unsigned long i;
229*4882a593Smuzhiyun pgoff_t pgoff;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * In the device-dax case the only possibility for a
233*4882a593Smuzhiyun * VM_FAULT_NOPAGE result is when device-dax capacity is
234*4882a593Smuzhiyun * mapped. No need to consider the zero page, or racing
235*4882a593Smuzhiyun * conflicting mappings.
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun pgoff = linear_page_index(vmf->vma, vmf->address
238*4882a593Smuzhiyun & ~(fault_size - 1));
239*4882a593Smuzhiyun for (i = 0; i < fault_size / PAGE_SIZE; i++) {
240*4882a593Smuzhiyun struct page *page;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun page = pfn_to_page(pfn_t_to_pfn(pfn) + i);
243*4882a593Smuzhiyun if (page->mapping)
244*4882a593Smuzhiyun continue;
245*4882a593Smuzhiyun page->mapping = filp->f_mapping;
246*4882a593Smuzhiyun page->index = pgoff + i;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun dax_read_unlock(id);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun return rc;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
dev_dax_fault(struct vm_fault * vmf)254*4882a593Smuzhiyun static vm_fault_t dev_dax_fault(struct vm_fault *vmf)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun return dev_dax_huge_fault(vmf, PE_SIZE_PTE);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
dev_dax_split(struct vm_area_struct * vma,unsigned long addr)259*4882a593Smuzhiyun static int dev_dax_split(struct vm_area_struct *vma, unsigned long addr)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct file *filp = vma->vm_file;
262*4882a593Smuzhiyun struct dev_dax *dev_dax = filp->private_data;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (!IS_ALIGNED(addr, dev_dax->align))
265*4882a593Smuzhiyun return -EINVAL;
266*4882a593Smuzhiyun return 0;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
dev_dax_pagesize(struct vm_area_struct * vma)269*4882a593Smuzhiyun static unsigned long dev_dax_pagesize(struct vm_area_struct *vma)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct file *filp = vma->vm_file;
272*4882a593Smuzhiyun struct dev_dax *dev_dax = filp->private_data;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun return dev_dax->align;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun static const struct vm_operations_struct dax_vm_ops = {
278*4882a593Smuzhiyun .fault = dev_dax_fault,
279*4882a593Smuzhiyun .huge_fault = dev_dax_huge_fault,
280*4882a593Smuzhiyun .split = dev_dax_split,
281*4882a593Smuzhiyun .pagesize = dev_dax_pagesize,
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun
dax_mmap(struct file * filp,struct vm_area_struct * vma)284*4882a593Smuzhiyun static int dax_mmap(struct file *filp, struct vm_area_struct *vma)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun struct dev_dax *dev_dax = filp->private_data;
287*4882a593Smuzhiyun int rc, id;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun dev_dbg(&dev_dax->dev, "trace\n");
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun /*
292*4882a593Smuzhiyun * We lock to check dax_dev liveness and will re-check at
293*4882a593Smuzhiyun * fault time.
294*4882a593Smuzhiyun */
295*4882a593Smuzhiyun id = dax_read_lock();
296*4882a593Smuzhiyun rc = check_vma(dev_dax, vma, __func__);
297*4882a593Smuzhiyun dax_read_unlock(id);
298*4882a593Smuzhiyun if (rc)
299*4882a593Smuzhiyun return rc;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun vma->vm_ops = &dax_vm_ops;
302*4882a593Smuzhiyun vma->vm_flags |= VM_HUGEPAGE;
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* return an unmapped area aligned to the dax region specified alignment */
dax_get_unmapped_area(struct file * filp,unsigned long addr,unsigned long len,unsigned long pgoff,unsigned long flags)307*4882a593Smuzhiyun static unsigned long dax_get_unmapped_area(struct file *filp,
308*4882a593Smuzhiyun unsigned long addr, unsigned long len, unsigned long pgoff,
309*4882a593Smuzhiyun unsigned long flags)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun unsigned long off, off_end, off_align, len_align, addr_align, align;
312*4882a593Smuzhiyun struct dev_dax *dev_dax = filp ? filp->private_data : NULL;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (!dev_dax || addr)
315*4882a593Smuzhiyun goto out;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun align = dev_dax->align;
318*4882a593Smuzhiyun off = pgoff << PAGE_SHIFT;
319*4882a593Smuzhiyun off_end = off + len;
320*4882a593Smuzhiyun off_align = round_up(off, align);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if ((off_end <= off_align) || ((off_end - off_align) < align))
323*4882a593Smuzhiyun goto out;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun len_align = len + align;
326*4882a593Smuzhiyun if ((off + len_align) < off)
327*4882a593Smuzhiyun goto out;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun addr_align = current->mm->get_unmapped_area(filp, addr, len_align,
330*4882a593Smuzhiyun pgoff, flags);
331*4882a593Smuzhiyun if (!IS_ERR_VALUE(addr_align)) {
332*4882a593Smuzhiyun addr_align += (off - addr_align) & (align - 1);
333*4882a593Smuzhiyun return addr_align;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun out:
336*4882a593Smuzhiyun return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun static const struct address_space_operations dev_dax_aops = {
340*4882a593Smuzhiyun .set_page_dirty = noop_set_page_dirty,
341*4882a593Smuzhiyun .invalidatepage = noop_invalidatepage,
342*4882a593Smuzhiyun };
343*4882a593Smuzhiyun
dax_open(struct inode * inode,struct file * filp)344*4882a593Smuzhiyun static int dax_open(struct inode *inode, struct file *filp)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct dax_device *dax_dev = inode_dax(inode);
347*4882a593Smuzhiyun struct inode *__dax_inode = dax_inode(dax_dev);
348*4882a593Smuzhiyun struct dev_dax *dev_dax = dax_get_private(dax_dev);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun dev_dbg(&dev_dax->dev, "trace\n");
351*4882a593Smuzhiyun inode->i_mapping = __dax_inode->i_mapping;
352*4882a593Smuzhiyun inode->i_mapping->host = __dax_inode;
353*4882a593Smuzhiyun inode->i_mapping->a_ops = &dev_dax_aops;
354*4882a593Smuzhiyun filp->f_mapping = inode->i_mapping;
355*4882a593Smuzhiyun filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
356*4882a593Smuzhiyun filp->f_sb_err = file_sample_sb_err(filp);
357*4882a593Smuzhiyun filp->private_data = dev_dax;
358*4882a593Smuzhiyun inode->i_flags = S_DAX;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun return 0;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
dax_release(struct inode * inode,struct file * filp)363*4882a593Smuzhiyun static int dax_release(struct inode *inode, struct file *filp)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun struct dev_dax *dev_dax = filp->private_data;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun dev_dbg(&dev_dax->dev, "trace\n");
368*4882a593Smuzhiyun return 0;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun static const struct file_operations dax_fops = {
372*4882a593Smuzhiyun .llseek = noop_llseek,
373*4882a593Smuzhiyun .owner = THIS_MODULE,
374*4882a593Smuzhiyun .open = dax_open,
375*4882a593Smuzhiyun .release = dax_release,
376*4882a593Smuzhiyun .get_unmapped_area = dax_get_unmapped_area,
377*4882a593Smuzhiyun .mmap = dax_mmap,
378*4882a593Smuzhiyun .mmap_supported_flags = MAP_SYNC,
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun
dev_dax_cdev_del(void * cdev)381*4882a593Smuzhiyun static void dev_dax_cdev_del(void *cdev)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun cdev_del(cdev);
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
dev_dax_kill(void * dev_dax)386*4882a593Smuzhiyun static void dev_dax_kill(void *dev_dax)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun kill_dev_dax(dev_dax);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
dev_dax_probe(struct dev_dax * dev_dax)391*4882a593Smuzhiyun int dev_dax_probe(struct dev_dax *dev_dax)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct dax_device *dax_dev = dev_dax->dax_dev;
394*4882a593Smuzhiyun struct device *dev = &dev_dax->dev;
395*4882a593Smuzhiyun struct dev_pagemap *pgmap;
396*4882a593Smuzhiyun struct inode *inode;
397*4882a593Smuzhiyun struct cdev *cdev;
398*4882a593Smuzhiyun void *addr;
399*4882a593Smuzhiyun int rc, i;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun pgmap = dev_dax->pgmap;
402*4882a593Smuzhiyun if (dev_WARN_ONCE(dev, pgmap && dev_dax->nr_range > 1,
403*4882a593Smuzhiyun "static pgmap / multi-range device conflict\n"))
404*4882a593Smuzhiyun return -EINVAL;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (!pgmap) {
407*4882a593Smuzhiyun pgmap = devm_kzalloc(dev, sizeof(*pgmap) + sizeof(struct range)
408*4882a593Smuzhiyun * (dev_dax->nr_range - 1), GFP_KERNEL);
409*4882a593Smuzhiyun if (!pgmap)
410*4882a593Smuzhiyun return -ENOMEM;
411*4882a593Smuzhiyun pgmap->nr_range = dev_dax->nr_range;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun for (i = 0; i < dev_dax->nr_range; i++) {
415*4882a593Smuzhiyun struct range *range = &dev_dax->ranges[i].range;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (!devm_request_mem_region(dev, range->start,
418*4882a593Smuzhiyun range_len(range), dev_name(dev))) {
419*4882a593Smuzhiyun dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve range\n",
420*4882a593Smuzhiyun i, range->start, range->end);
421*4882a593Smuzhiyun return -EBUSY;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun /* don't update the range for static pgmap */
424*4882a593Smuzhiyun if (!dev_dax->pgmap)
425*4882a593Smuzhiyun pgmap->ranges[i] = *range;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun pgmap->type = MEMORY_DEVICE_GENERIC;
429*4882a593Smuzhiyun addr = devm_memremap_pages(dev, pgmap);
430*4882a593Smuzhiyun if (IS_ERR(addr))
431*4882a593Smuzhiyun return PTR_ERR(addr);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun inode = dax_inode(dax_dev);
434*4882a593Smuzhiyun cdev = inode->i_cdev;
435*4882a593Smuzhiyun cdev_init(cdev, &dax_fops);
436*4882a593Smuzhiyun if (dev->class) {
437*4882a593Smuzhiyun /* for the CONFIG_DEV_DAX_PMEM_COMPAT case */
438*4882a593Smuzhiyun cdev->owner = dev->parent->driver->owner;
439*4882a593Smuzhiyun } else
440*4882a593Smuzhiyun cdev->owner = dev->driver->owner;
441*4882a593Smuzhiyun cdev_set_parent(cdev, &dev->kobj);
442*4882a593Smuzhiyun rc = cdev_add(cdev, dev->devt, 1);
443*4882a593Smuzhiyun if (rc)
444*4882a593Smuzhiyun return rc;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun rc = devm_add_action_or_reset(dev, dev_dax_cdev_del, cdev);
447*4882a593Smuzhiyun if (rc)
448*4882a593Smuzhiyun return rc;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun run_dax(dax_dev);
451*4882a593Smuzhiyun return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dev_dax_probe);
454*4882a593Smuzhiyun
dev_dax_remove(struct dev_dax * dev_dax)455*4882a593Smuzhiyun static int dev_dax_remove(struct dev_dax *dev_dax)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun /* all probe actions are unwound by devm */
458*4882a593Smuzhiyun return 0;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun static struct dax_device_driver device_dax_driver = {
462*4882a593Smuzhiyun .probe = dev_dax_probe,
463*4882a593Smuzhiyun .remove = dev_dax_remove,
464*4882a593Smuzhiyun .match_always = 1,
465*4882a593Smuzhiyun };
466*4882a593Smuzhiyun
dax_init(void)467*4882a593Smuzhiyun static int __init dax_init(void)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun return dax_driver_register(&device_dax_driver);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
dax_exit(void)472*4882a593Smuzhiyun static void __exit dax_exit(void)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun dax_driver_unregister(&device_dax_driver);
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun MODULE_AUTHOR("Intel Corporation");
478*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
479*4882a593Smuzhiyun module_init(dax_init);
480*4882a593Smuzhiyun module_exit(dax_exit);
481*4882a593Smuzhiyun MODULE_ALIAS_DAX_DEVICE(0);
482