diff options
Diffstat (limited to 'lib/iomap.c')
-rw-r--r-- | lib/iomap.c | 296 |
1 files changed, 0 insertions, 296 deletions
diff --git a/lib/iomap.c b/lib/iomap.c index 4990c736bc4b..4d43f37c0154 100644 --- a/lib/iomap.c +++ b/lib/iomap.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <linux/pci.h> | 6 | #include <linux/pci.h> |
7 | #include <linux/io.h> | 7 | #include <linux/io.h> |
8 | 8 | ||
9 | #ifdef CONFIG_GENERIC_IOMAP | ||
10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
11 | 10 | ||
12 | /* | 11 | /* |
@@ -256,298 +255,3 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | |||
256 | } | 255 | } |
257 | EXPORT_SYMBOL(pci_iomap); | 256 | EXPORT_SYMBOL(pci_iomap); |
258 | EXPORT_SYMBOL(pci_iounmap); | 257 | EXPORT_SYMBOL(pci_iounmap); |
259 | |||
260 | #endif /* CONFIG_GENERIC_IOMAP */ | ||
261 | |||
262 | /* | ||
263 | * Generic iomap devres | ||
264 | */ | ||
265 | static void devm_ioport_map_release(struct device *dev, void *res) | ||
266 | { | ||
267 | ioport_unmap(*(void __iomem **)res); | ||
268 | } | ||
269 | |||
270 | static int devm_ioport_map_match(struct device *dev, void *res, | ||
271 | void *match_data) | ||
272 | { | ||
273 | return *(void **)res == match_data; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * devm_ioport_map - Managed ioport_map() | ||
278 | * @dev: Generic device to map ioport for | ||
279 | * @port: Port to map | ||
280 | * @nr: Number of ports to map | ||
281 | * | ||
282 | * Managed ioport_map(). Map is automatically unmapped on driver | ||
283 | * detach. | ||
284 | */ | ||
285 | void __iomem * devm_ioport_map(struct device *dev, unsigned long port, | ||
286 | unsigned int nr) | ||
287 | { | ||
288 | void __iomem **ptr, *addr; | ||
289 | |||
290 | ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL); | ||
291 | if (!ptr) | ||
292 | return NULL; | ||
293 | |||
294 | addr = ioport_map(port, nr); | ||
295 | if (addr) { | ||
296 | *ptr = addr; | ||
297 | devres_add(dev, ptr); | ||
298 | } else | ||
299 | devres_free(ptr); | ||
300 | |||
301 | return addr; | ||
302 | } | ||
303 | EXPORT_SYMBOL(devm_ioport_map); | ||
304 | |||
305 | /** | ||
306 | * devm_ioport_unmap - Managed ioport_unmap() | ||
307 | * @dev: Generic device to unmap for | ||
308 | * @addr: Address to unmap | ||
309 | * | ||
310 | * Managed ioport_unmap(). @addr must have been mapped using | ||
311 | * devm_ioport_map(). | ||
312 | */ | ||
313 | void devm_ioport_unmap(struct device *dev, void __iomem *addr) | ||
314 | { | ||
315 | ioport_unmap(addr); | ||
316 | WARN_ON(devres_destroy(dev, devm_ioport_map_release, | ||
317 | devm_ioport_map_match, (void *)addr)); | ||
318 | } | ||
319 | EXPORT_SYMBOL(devm_ioport_unmap); | ||
320 | |||
321 | static void devm_ioremap_release(struct device *dev, void *res) | ||
322 | { | ||
323 | iounmap(*(void __iomem **)res); | ||
324 | } | ||
325 | |||
326 | static int devm_ioremap_match(struct device *dev, void *res, void *match_data) | ||
327 | { | ||
328 | return *(void **)res == match_data; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * devm_ioremap - Managed ioremap() | ||
333 | * @dev: Generic device to remap IO address for | ||
334 | * @offset: BUS offset to map | ||
335 | * @size: Size of map | ||
336 | * | ||
337 | * Managed ioremap(). Map is automatically unmapped on driver detach. | ||
338 | */ | ||
339 | void __iomem *devm_ioremap(struct device *dev, unsigned long offset, | ||
340 | unsigned long size) | ||
341 | { | ||
342 | void __iomem **ptr, *addr; | ||
343 | |||
344 | ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); | ||
345 | if (!ptr) | ||
346 | return NULL; | ||
347 | |||
348 | addr = ioremap(offset, size); | ||
349 | if (addr) { | ||
350 | *ptr = addr; | ||
351 | devres_add(dev, ptr); | ||
352 | } else | ||
353 | devres_free(ptr); | ||
354 | |||
355 | return addr; | ||
356 | } | ||
357 | EXPORT_SYMBOL(devm_ioremap); | ||
358 | |||
359 | /** | ||
360 | * devm_ioremap_nocache - Managed ioremap_nocache() | ||
361 | * @dev: Generic device to remap IO address for | ||
362 | * @offset: BUS offset to map | ||
363 | * @size: Size of map | ||
364 | * | ||
365 | * Managed ioremap_nocache(). Map is automatically unmapped on driver | ||
366 | * detach. | ||
367 | */ | ||
368 | void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset, | ||
369 | unsigned long size) | ||
370 | { | ||
371 | void __iomem **ptr, *addr; | ||
372 | |||
373 | ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); | ||
374 | if (!ptr) | ||
375 | return NULL; | ||
376 | |||
377 | addr = ioremap_nocache(offset, size); | ||
378 | if (addr) { | ||
379 | *ptr = addr; | ||
380 | devres_add(dev, ptr); | ||
381 | } else | ||
382 | devres_free(ptr); | ||
383 | |||
384 | return addr; | ||
385 | } | ||
386 | EXPORT_SYMBOL(devm_ioremap_nocache); | ||
387 | |||
388 | /** | ||
389 | * devm_iounmap - Managed iounmap() | ||
390 | * @dev: Generic device to unmap for | ||
391 | * @addr: Address to unmap | ||
392 | * | ||
393 | * Managed iounmap(). @addr must have been mapped using devm_ioremap*(). | ||
394 | */ | ||
395 | void devm_iounmap(struct device *dev, void __iomem *addr) | ||
396 | { | ||
397 | iounmap(addr); | ||
398 | WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match, | ||
399 | (void *)addr)); | ||
400 | } | ||
401 | EXPORT_SYMBOL(devm_iounmap); | ||
402 | |||
403 | /* | ||
404 | * PCI iomap devres | ||
405 | */ | ||
406 | #define PCIM_IOMAP_MAX PCI_ROM_RESOURCE | ||
407 | |||
408 | struct pcim_iomap_devres { | ||
409 | void __iomem *table[PCIM_IOMAP_MAX]; | ||
410 | }; | ||
411 | |||
412 | static void pcim_iomap_release(struct device *gendev, void *res) | ||
413 | { | ||
414 | struct pci_dev *dev = container_of(gendev, struct pci_dev, dev); | ||
415 | struct pcim_iomap_devres *this = res; | ||
416 | int i; | ||
417 | |||
418 | for (i = 0; i < PCIM_IOMAP_MAX; i++) | ||
419 | if (this->table[i]) | ||
420 | pci_iounmap(dev, this->table[i]); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * pcim_iomap_table - access iomap allocation table | ||
425 | * @pdev: PCI device to access iomap table for | ||
426 | * | ||
427 | * Access iomap allocation table for @dev. If iomap table doesn't | ||
428 | * exist and @pdev is managed, it will be allocated. All iomaps | ||
429 | * recorded in the iomap table are automatically unmapped on driver | ||
430 | * detach. | ||
431 | * | ||
432 | * This function might sleep when the table is first allocated but can | ||
433 | * be safely called without context and guaranteed to succed once | ||
434 | * allocated. | ||
435 | */ | ||
436 | void __iomem * const * pcim_iomap_table(struct pci_dev *pdev) | ||
437 | { | ||
438 | struct pcim_iomap_devres *dr, *new_dr; | ||
439 | |||
440 | dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL); | ||
441 | if (dr) | ||
442 | return dr->table; | ||
443 | |||
444 | new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL); | ||
445 | if (!new_dr) | ||
446 | return NULL; | ||
447 | dr = devres_get(&pdev->dev, new_dr, NULL, NULL); | ||
448 | return dr->table; | ||
449 | } | ||
450 | EXPORT_SYMBOL(pcim_iomap_table); | ||
451 | |||
452 | /** | ||
453 | * pcim_iomap - Managed pcim_iomap() | ||
454 | * @pdev: PCI device to iomap for | ||
455 | * @bar: BAR to iomap | ||
456 | * @maxlen: Maximum length of iomap | ||
457 | * | ||
458 | * Managed pci_iomap(). Map is automatically unmapped on driver | ||
459 | * detach. | ||
460 | */ | ||
461 | void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) | ||
462 | { | ||
463 | void __iomem **tbl; | ||
464 | |||
465 | BUG_ON(bar >= PCIM_IOMAP_MAX); | ||
466 | |||
467 | tbl = (void __iomem **)pcim_iomap_table(pdev); | ||
468 | if (!tbl || tbl[bar]) /* duplicate mappings not allowed */ | ||
469 | return NULL; | ||
470 | |||
471 | tbl[bar] = pci_iomap(pdev, bar, maxlen); | ||
472 | return tbl[bar]; | ||
473 | } | ||
474 | EXPORT_SYMBOL(pcim_iomap); | ||
475 | |||
476 | /** | ||
477 | * pcim_iounmap - Managed pci_iounmap() | ||
478 | * @pdev: PCI device to iounmap for | ||
479 | * @addr: Address to unmap | ||
480 | * | ||
481 | * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap(). | ||
482 | */ | ||
483 | void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr) | ||
484 | { | ||
485 | void __iomem **tbl; | ||
486 | int i; | ||
487 | |||
488 | pci_iounmap(pdev, addr); | ||
489 | |||
490 | tbl = (void __iomem **)pcim_iomap_table(pdev); | ||
491 | BUG_ON(!tbl); | ||
492 | |||
493 | for (i = 0; i < PCIM_IOMAP_MAX; i++) | ||
494 | if (tbl[i] == addr) { | ||
495 | tbl[i] = NULL; | ||
496 | return; | ||
497 | } | ||
498 | WARN_ON(1); | ||
499 | } | ||
500 | EXPORT_SYMBOL(pcim_iounmap); | ||
501 | |||
502 | /** | ||
503 | * pcim_iomap_regions - Request and iomap PCI BARs | ||
504 | * @pdev: PCI device to map IO resources for | ||
505 | * @mask: Mask of BARs to request and iomap | ||
506 | * @name: Name used when requesting regions | ||
507 | * | ||
508 | * Request and iomap regions specified by @mask. | ||
509 | */ | ||
510 | int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name) | ||
511 | { | ||
512 | void __iomem * const *iomap; | ||
513 | int i, rc; | ||
514 | |||
515 | iomap = pcim_iomap_table(pdev); | ||
516 | if (!iomap) | ||
517 | return -ENOMEM; | ||
518 | |||
519 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
520 | unsigned long len; | ||
521 | |||
522 | if (!(mask & (1 << i))) | ||
523 | continue; | ||
524 | |||
525 | rc = -EINVAL; | ||
526 | len = pci_resource_len(pdev, i); | ||
527 | if (!len) | ||
528 | goto err_inval; | ||
529 | |||
530 | rc = pci_request_region(pdev, i, name); | ||
531 | if (rc) | ||
532 | goto err_region; | ||
533 | |||
534 | rc = -ENOMEM; | ||
535 | if (!pcim_iomap(pdev, i, 0)) | ||
536 | goto err_iomap; | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | |||
541 | err_iomap: | ||
542 | pcim_iounmap(pdev, iomap[i]); | ||
543 | err_region: | ||
544 | pci_release_region(pdev, i); | ||
545 | err_inval: | ||
546 | while (--i >= 0) { | ||
547 | pcim_iounmap(pdev, iomap[i]); | ||
548 | pci_release_region(pdev, i); | ||
549 | } | ||
550 | |||
551 | return rc; | ||
552 | } | ||
553 | EXPORT_SYMBOL(pcim_iomap_regions); | ||