]> git.ipfire.org Git - people/ms/linux.git/blame - kernel/memremap.c
pmem: convert to generic memremap
[people/ms/linux.git] / kernel / memremap.c
CommitLineData
92281dee
DW
1/*
2 * Copyright(c) 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/types.h>
14#include <linux/io.h>
15#include <linux/mm.h>
16
17#ifndef ioremap_cache
18/* temporary while we convert existing ioremap_cache users to memremap */
19__weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
20{
21 return ioremap(offset, size);
22}
23#endif
24
25/**
26 * memremap() - remap an iomem_resource as cacheable memory
27 * @offset: iomem resource start address
28 * @size: size of remap
29 * @flags: either MEMREMAP_WB or MEMREMAP_WT
30 *
31 * memremap() is "ioremap" for cases where it is known that the resource
32 * being mapped does not have i/o side effects and the __iomem
33 * annotation is not applicable.
34 *
35 * MEMREMAP_WB - matches the default mapping for "System RAM" on
36 * the architecture. This is usually a read-allocate write-back cache.
37 * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
38 * memremap() will bypass establishing a new mapping and instead return
39 * a pointer into the direct map.
40 *
41 * MEMREMAP_WT - establish a mapping whereby writes either bypass the
42 * cache or are written through to memory and never exist in a
43 * cache-dirty state with respect to program visibility. Attempts to
44 * map "System RAM" with this mapping type will fail.
45 */
46void *memremap(resource_size_t offset, size_t size, unsigned long flags)
47{
48 int is_ram = region_intersects(offset, size, "System RAM");
49 void *addr = NULL;
50
51 if (is_ram == REGION_MIXED) {
52 WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
53 &offset, (unsigned long) size);
54 return NULL;
55 }
56
57 /* Try all mapping types requested until one returns non-NULL */
58 if (flags & MEMREMAP_WB) {
59 flags &= ~MEMREMAP_WB;
60 /*
61 * MEMREMAP_WB is special in that it can be satisifed
62 * from the direct map. Some archs depend on the
63 * capability of memremap() to autodetect cases where
64 * the requested range is potentially in "System RAM"
65 */
66 if (is_ram == REGION_INTERSECTS)
67 addr = __va(offset);
68 else
69 addr = ioremap_cache(offset, size);
70 }
71
72 /*
73 * If we don't have a mapping yet and more request flags are
74 * pending then we will be attempting to establish a new virtual
75 * address mapping. Enforce that this mapping is not aliasing
76 * "System RAM"
77 */
78 if (!addr && is_ram == REGION_INTERSECTS && flags) {
79 WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
80 &offset, (unsigned long) size);
81 return NULL;
82 }
83
84 if (!addr && (flags & MEMREMAP_WT)) {
85 flags &= ~MEMREMAP_WT;
86 addr = ioremap_wt(offset, size);
87 }
88
89 return addr;
90}
91EXPORT_SYMBOL(memremap);
92
93void memunmap(void *addr)
94{
95 if (is_vmalloc_addr(addr))
96 iounmap((void __iomem *) addr);
97}
98EXPORT_SYMBOL(memunmap);