2 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
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.
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.
13 #include <linux/rculist.h>
14 #include <linux/export.h>
15 #include <linux/ioport.h>
16 #include <linux/module.h>
17 #include <linux/types.h>
19 #include "nfit_test.h"
21 static LIST_HEAD(iomap_head
);
23 static struct iomap_ops
{
24 nfit_test_lookup_fn nfit_test_lookup
;
25 struct list_head list
;
27 .list
= LIST_HEAD_INIT(iomap_ops
.list
),
30 void nfit_test_setup(nfit_test_lookup_fn lookup
)
32 iomap_ops
.nfit_test_lookup
= lookup
;
33 list_add_rcu(&iomap_ops
.list
, &iomap_head
);
35 EXPORT_SYMBOL(nfit_test_setup
);
37 void nfit_test_teardown(void)
39 list_del_rcu(&iomap_ops
.list
);
42 EXPORT_SYMBOL(nfit_test_teardown
);
44 static struct nfit_test_resource
*get_nfit_res(resource_size_t resource
)
46 struct iomap_ops
*ops
;
48 ops
= list_first_or_null_rcu(&iomap_head
, typeof(*ops
), list
);
50 return ops
->nfit_test_lookup(resource
);
54 void __iomem
*__nfit_test_ioremap(resource_size_t offset
, unsigned long size
,
55 void __iomem
*(*fallback_fn
)(resource_size_t
, unsigned long))
57 struct nfit_test_resource
*nfit_res
;
60 nfit_res
= get_nfit_res(offset
);
63 return (void __iomem
*) nfit_res
->buf
+ offset
64 - nfit_res
->res
->start
;
65 return fallback_fn(offset
, size
);
68 void __iomem
*__wrap_devm_ioremap_nocache(struct device
*dev
,
69 resource_size_t offset
, unsigned long size
)
71 struct nfit_test_resource
*nfit_res
;
74 nfit_res
= get_nfit_res(offset
);
77 return (void __iomem
*) nfit_res
->buf
+ offset
78 - nfit_res
->res
->start
;
79 return devm_ioremap_nocache(dev
, offset
, size
);
81 EXPORT_SYMBOL(__wrap_devm_ioremap_nocache
);
83 void *__wrap_devm_memremap(struct device
*dev
, resource_size_t offset
,
84 size_t size
, unsigned long flags
)
86 struct nfit_test_resource
*nfit_res
;
89 nfit_res
= get_nfit_res(offset
);
92 return nfit_res
->buf
+ offset
- nfit_res
->res
->start
;
93 return devm_memremap(dev
, offset
, size
, flags
);
95 EXPORT_SYMBOL(__wrap_devm_memremap
);
97 void *__wrap_memremap(resource_size_t offset
, size_t size
,
100 struct nfit_test_resource
*nfit_res
;
103 nfit_res
= get_nfit_res(offset
);
106 return nfit_res
->buf
+ offset
- nfit_res
->res
->start
;
107 return memremap(offset
, size
, flags
);
109 EXPORT_SYMBOL(__wrap_memremap
);
111 void __wrap_devm_memunmap(struct device
*dev
, void *addr
)
113 struct nfit_test_resource
*nfit_res
;
116 nfit_res
= get_nfit_res((unsigned long) addr
);
120 return devm_memunmap(dev
, addr
);
122 EXPORT_SYMBOL(__wrap_devm_memunmap
);
124 void __iomem
*__wrap_ioremap_nocache(resource_size_t offset
, unsigned long size
)
126 return __nfit_test_ioremap(offset
, size
, ioremap_nocache
);
128 EXPORT_SYMBOL(__wrap_ioremap_nocache
);
130 void __iomem
*__wrap_ioremap_wc(resource_size_t offset
, unsigned long size
)
132 return __nfit_test_ioremap(offset
, size
, ioremap_wc
);
134 EXPORT_SYMBOL(__wrap_ioremap_wc
);
136 void __wrap_iounmap(volatile void __iomem
*addr
)
138 struct nfit_test_resource
*nfit_res
;
141 nfit_res
= get_nfit_res((unsigned long) addr
);
145 return iounmap(addr
);
147 EXPORT_SYMBOL(__wrap_iounmap
);
149 void __wrap_memunmap(void *addr
)
151 struct nfit_test_resource
*nfit_res
;
154 nfit_res
= get_nfit_res((unsigned long) addr
);
158 return memunmap(addr
);
160 EXPORT_SYMBOL(__wrap_memunmap
);
162 static struct resource
*nfit_test_request_region(struct device
*dev
,
163 struct resource
*parent
, resource_size_t start
,
164 resource_size_t n
, const char *name
, int flags
)
166 struct nfit_test_resource
*nfit_res
;
168 if (parent
== &iomem_resource
) {
170 nfit_res
= get_nfit_res(start
);
173 struct resource
*res
= nfit_res
->res
+ 1;
175 if (start
+ n
> nfit_res
->res
->start
176 + resource_size(nfit_res
->res
)) {
177 pr_debug("%s: start: %llx n: %llx overflow: %pr\n",
184 res
->end
= start
+ n
- 1;
186 res
->flags
= resource_type(parent
);
187 res
->flags
|= IORESOURCE_BUSY
| flags
;
188 pr_debug("%s: %pr\n", __func__
, res
);
193 return __devm_request_region(dev
, parent
, start
, n
, name
);
194 return __request_region(parent
, start
, n
, name
, flags
);
197 struct resource
*__wrap___request_region(struct resource
*parent
,
198 resource_size_t start
, resource_size_t n
, const char *name
,
201 return nfit_test_request_region(NULL
, parent
, start
, n
, name
, flags
);
203 EXPORT_SYMBOL(__wrap___request_region
);
205 struct resource
*__wrap___devm_request_region(struct device
*dev
,
206 struct resource
*parent
, resource_size_t start
,
207 resource_size_t n
, const char *name
)
211 return nfit_test_request_region(dev
, parent
, start
, n
, name
, 0);
213 EXPORT_SYMBOL(__wrap___devm_request_region
);
215 void __wrap___release_region(struct resource
*parent
, resource_size_t start
,
218 struct nfit_test_resource
*nfit_res
;
220 if (parent
== &iomem_resource
) {
222 nfit_res
= get_nfit_res(start
);
225 struct resource
*res
= nfit_res
->res
+ 1;
227 if (start
!= res
->start
|| resource_size(res
) != n
)
228 pr_info("%s: start: %llx n: %llx mismatch: %pr\n",
229 __func__
, start
, n
, res
);
231 memset(res
, 0, sizeof(*res
));
235 __release_region(parent
, start
, n
);
237 EXPORT_SYMBOL(__wrap___release_region
);
239 MODULE_LICENSE("GPL v2");