1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Generic PCI resource mmap helper |
4 | * |
5 | * Copyright © 2017 Amazon.com, Inc. or its affiliates. |
6 | * |
7 | * Author: David Woodhouse <dwmw2@infradead.org> |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/mm.h> |
12 | #include <linux/pci.h> |
13 | |
14 | #ifdef ARCH_GENERIC_PCI_MMAP_RESOURCE |
15 | |
16 | static const struct vm_operations_struct pci_phys_vm_ops = { |
17 | #ifdef CONFIG_HAVE_IOREMAP_PROT |
18 | .access = generic_access_phys, |
19 | #endif |
20 | }; |
21 | |
22 | int pci_mmap_resource_range(struct pci_dev *pdev, int bar, |
23 | struct vm_area_struct *vma, |
24 | enum pci_mmap_state mmap_state, int write_combine) |
25 | { |
26 | unsigned long size; |
27 | int ret; |
28 | |
29 | size = ((pci_resource_len(pdev, bar) - 1) >> PAGE_SHIFT) + 1; |
30 | if (vma->vm_pgoff + vma_pages(vma) > size) |
31 | return -EINVAL; |
32 | |
33 | if (write_combine) |
34 | vma->vm_page_prot = pgprot_writecombine(prot: vma->vm_page_prot); |
35 | else |
36 | vma->vm_page_prot = pgprot_device(vma->vm_page_prot); |
37 | |
38 | if (mmap_state == pci_mmap_io) { |
39 | ret = pci_iobar_pfn(pdev, bar, vma); |
40 | if (ret) |
41 | return ret; |
42 | } else |
43 | vma->vm_pgoff += (pci_resource_start(pdev, bar) >> PAGE_SHIFT); |
44 | |
45 | vma->vm_ops = &pci_phys_vm_ops; |
46 | |
47 | return io_remap_pfn_range(vma, addr: vma->vm_start, pfn: vma->vm_pgoff, |
48 | size: vma->vm_end - vma->vm_start, |
49 | prot: vma->vm_page_prot); |
50 | } |
51 | |
52 | #endif |
53 | |