@@ -74,7 +74,7 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
7474
7575 if (nfit_res )
7676 return (void __iomem * ) nfit_res -> buf + offset
77- - nfit_res -> res -> start ;
77+ - nfit_res -> res . start ;
7878 return fallback_fn (offset , size );
7979}
8080
@@ -85,7 +85,7 @@ void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
8585
8686 if (nfit_res )
8787 return (void __iomem * ) nfit_res -> buf + offset
88- - nfit_res -> res -> start ;
88+ - nfit_res -> res . start ;
8989 return devm_ioremap_nocache (dev , offset , size );
9090}
9191EXPORT_SYMBOL (__wrap_devm_ioremap_nocache );
@@ -96,7 +96,7 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
9696 struct nfit_test_resource * nfit_res = get_nfit_res (offset );
9797
9898 if (nfit_res )
99- return nfit_res -> buf + offset - nfit_res -> res -> start ;
99+ return nfit_res -> buf + offset - nfit_res -> res . start ;
100100 return devm_memremap (dev , offset , size , flags );
101101}
102102EXPORT_SYMBOL (__wrap_devm_memremap );
@@ -108,7 +108,7 @@ void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
108108 struct nfit_test_resource * nfit_res = get_nfit_res (offset );
109109
110110 if (nfit_res )
111- return nfit_res -> buf + offset - nfit_res -> res -> start ;
111+ return nfit_res -> buf + offset - nfit_res -> res . start ;
112112 return devm_memremap_pages (dev , res , ref , altmap );
113113}
114114EXPORT_SYMBOL (__wrap_devm_memremap_pages );
@@ -129,7 +129,7 @@ void *__wrap_memremap(resource_size_t offset, size_t size,
129129 struct nfit_test_resource * nfit_res = get_nfit_res (offset );
130130
131131 if (nfit_res )
132- return nfit_res -> buf + offset - nfit_res -> res -> start ;
132+ return nfit_res -> buf + offset - nfit_res -> res . start ;
133133 return memremap (offset , size , flags );
134134}
135135EXPORT_SYMBOL (__wrap_memremap );
@@ -175,6 +175,63 @@ void __wrap_memunmap(void *addr)
175175}
176176EXPORT_SYMBOL (__wrap_memunmap );
177177
178+ static bool nfit_test_release_region (struct device * dev ,
179+ struct resource * parent , resource_size_t start ,
180+ resource_size_t n );
181+
182+ static void nfit_devres_release (struct device * dev , void * data )
183+ {
184+ struct resource * res = * ((struct resource * * ) data );
185+
186+ WARN_ON (!nfit_test_release_region (NULL , & iomem_resource , res -> start ,
187+ resource_size (res )));
188+ }
189+
190+ static int match (struct device * dev , void * __res , void * match_data )
191+ {
192+ struct resource * res = * ((struct resource * * ) __res );
193+ resource_size_t start = * ((resource_size_t * ) match_data );
194+
195+ return res -> start == start ;
196+ }
197+
198+ static bool nfit_test_release_region (struct device * dev ,
199+ struct resource * parent , resource_size_t start ,
200+ resource_size_t n )
201+ {
202+ if (parent == & iomem_resource ) {
203+ struct nfit_test_resource * nfit_res = get_nfit_res (start );
204+
205+ if (nfit_res ) {
206+ struct nfit_test_request * req ;
207+ struct resource * res = NULL ;
208+
209+ if (dev ) {
210+ devres_release (dev , nfit_devres_release , match ,
211+ & start );
212+ return true;
213+ }
214+
215+ spin_lock (& nfit_res -> lock );
216+ list_for_each_entry (req , & nfit_res -> requests , list )
217+ if (req -> res .start == start ) {
218+ res = & req -> res ;
219+ list_del (& req -> list );
220+ break ;
221+ }
222+ spin_unlock (& nfit_res -> lock );
223+
224+ WARN (!res || resource_size (res ) != n ,
225+ "%s: start: %llx n: %llx mismatch: %pr\n" ,
226+ __func__ , start , n , res );
227+ if (res )
228+ kfree (req );
229+ return true;
230+ }
231+ }
232+ return false;
233+ }
234+
178235static struct resource * nfit_test_request_region (struct device * dev ,
179236 struct resource * parent , resource_size_t start ,
180237 resource_size_t n , const char * name , int flags )
@@ -184,21 +241,57 @@ static struct resource *nfit_test_request_region(struct device *dev,
184241 if (parent == & iomem_resource ) {
185242 nfit_res = get_nfit_res (start );
186243 if (nfit_res ) {
187- struct resource * res = nfit_res -> res + 1 ;
244+ struct nfit_test_request * req ;
245+ struct resource * res = NULL ;
188246
189- if (start + n > nfit_res -> res -> start
190- + resource_size (nfit_res -> res )) {
247+ if (start + n > nfit_res -> res . start
248+ + resource_size (& nfit_res -> res )) {
191249 pr_debug ("%s: start: %llx n: %llx overflow: %pr\n" ,
192250 __func__ , start , n ,
193- nfit_res -> res );
251+ & nfit_res -> res );
252+ return NULL ;
253+ }
254+
255+ spin_lock (& nfit_res -> lock );
256+ list_for_each_entry (req , & nfit_res -> requests , list )
257+ if (start == req -> res .start ) {
258+ res = & req -> res ;
259+ break ;
260+ }
261+ spin_unlock (& nfit_res -> lock );
262+
263+ if (res ) {
264+ WARN (1 , "%pr already busy\n" , res );
194265 return NULL ;
195266 }
196267
268+ req = kzalloc (sizeof (* req ), GFP_KERNEL );
269+ if (!req )
270+ return NULL ;
271+ INIT_LIST_HEAD (& req -> list );
272+ res = & req -> res ;
273+
197274 res -> start = start ;
198275 res -> end = start + n - 1 ;
199276 res -> name = name ;
200277 res -> flags = resource_type (parent );
201278 res -> flags |= IORESOURCE_BUSY | flags ;
279+ spin_lock (& nfit_res -> lock );
280+ list_add (& req -> list , & nfit_res -> requests );
281+ spin_unlock (& nfit_res -> lock );
282+
283+ if (dev ) {
284+ struct resource * * d ;
285+
286+ d = devres_alloc (nfit_devres_release ,
287+ sizeof (struct resource * ),
288+ GFP_KERNEL );
289+ if (!d )
290+ return NULL ;
291+ * d = res ;
292+ devres_add (dev , d );
293+ }
294+
202295 pr_debug ("%s: %pr\n" , __func__ , res );
203296 return res ;
204297 }
@@ -242,37 +335,18 @@ struct resource *__wrap___devm_request_region(struct device *dev,
242335}
243336EXPORT_SYMBOL (__wrap___devm_request_region );
244337
245- static bool nfit_test_release_region (struct resource * parent ,
246- resource_size_t start , resource_size_t n )
247- {
248- if (parent == & iomem_resource ) {
249- struct nfit_test_resource * nfit_res = get_nfit_res (start );
250- if (nfit_res ) {
251- struct resource * res = nfit_res -> res + 1 ;
252-
253- if (start != res -> start || resource_size (res ) != n )
254- pr_info ("%s: start: %llx n: %llx mismatch: %pr\n" ,
255- __func__ , start , n , res );
256- else
257- memset (res , 0 , sizeof (* res ));
258- return true;
259- }
260- }
261- return false;
262- }
263-
264338void __wrap___release_region (struct resource * parent , resource_size_t start ,
265339 resource_size_t n )
266340{
267- if (!nfit_test_release_region (parent , start , n ))
341+ if (!nfit_test_release_region (NULL , parent , start , n ))
268342 __release_region (parent , start , n );
269343}
270344EXPORT_SYMBOL (__wrap___release_region );
271345
272346void __wrap___devm_release_region (struct device * dev , struct resource * parent ,
273347 resource_size_t start , resource_size_t n )
274348{
275- if (!nfit_test_release_region (parent , start , n ))
349+ if (!nfit_test_release_region (dev , parent , start , n ))
276350 __devm_release_region (dev , parent , start , n );
277351}
278352EXPORT_SYMBOL (__wrap___devm_release_region );
0 commit comments