diff options
author | Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | 2009-07-10 12:57:34 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-08-26 18:41:10 -0400 |
commit | 9fd126bc742f74a95d2ba610247712ff05da02fe (patch) | |
tree | 2be99f0b80d6f5d07d2cff6bfddbb1b9313f026c | |
parent | 279e669b3fc0068cc3509e8e53036999e1e86588 (diff) |
x86, pat: New i/f for driver to request memtype for IO regions
Add new routines to request memtype for IO regions. This will currently
be a backend for io_mapping_* routines. But, it can also be made available
to drivers directly in future, in case it is needed.
reserve interface reserves the memory, makes sure we have a compatible
memory type available and keeps the identity map in sync when needed.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/include/asm/pat.h | 5 | ||||
-rw-r--r-- | arch/x86/mm/pat.c | 49 |
2 files changed, 54 insertions, 0 deletions
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h index 7af14e512f97..e2c1668dde7a 100644 --- a/arch/x86/include/asm/pat.h +++ b/arch/x86/include/asm/pat.h | |||
@@ -19,4 +19,9 @@ extern int free_memtype(u64 start, u64 end); | |||
19 | extern int kernel_map_sync_memtype(u64 base, unsigned long size, | 19 | extern int kernel_map_sync_memtype(u64 base, unsigned long size, |
20 | unsigned long flag); | 20 | unsigned long flag); |
21 | 21 | ||
22 | int io_reserve_memtype(resource_size_t start, resource_size_t end, | ||
23 | unsigned long *type); | ||
24 | |||
25 | void io_free_memtype(resource_size_t start, resource_size_t end); | ||
26 | |||
22 | #endif /* _ASM_X86_PAT_H */ | 27 | #endif /* _ASM_X86_PAT_H */ |
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index d5af2792d2fd..82d097ce3091 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -498,6 +498,55 @@ int free_memtype(u64 start, u64 end) | |||
498 | } | 498 | } |
499 | 499 | ||
500 | 500 | ||
501 | /** | ||
502 | * io_reserve_memtype - Request a memory type mapping for a region of memory | ||
503 | * @start: start (physical address) of the region | ||
504 | * @end: end (physical address) of the region | ||
505 | * @type: A pointer to memtype, with requested type. On success, requested | ||
506 | * or any other compatible type that was available for the region is returned | ||
507 | * | ||
508 | * On success, returns 0 | ||
509 | * On failure, returns non-zero | ||
510 | */ | ||
511 | int io_reserve_memtype(resource_size_t start, resource_size_t end, | ||
512 | unsigned long *type) | ||
513 | { | ||
514 | unsigned long req_type = *type; | ||
515 | unsigned long new_type; | ||
516 | int ret; | ||
517 | |||
518 | WARN_ON_ONCE(iomem_map_sanity_check(start, end - start)); | ||
519 | |||
520 | ret = reserve_memtype(start, end, req_type, &new_type); | ||
521 | if (ret) | ||
522 | goto out_err; | ||
523 | |||
524 | if (!is_new_memtype_allowed(req_type, new_type)) | ||
525 | goto out_free; | ||
526 | |||
527 | if (kernel_map_sync_memtype(start, end - start, new_type) < 0) | ||
528 | goto out_free; | ||
529 | |||
530 | *type = new_type; | ||
531 | return 0; | ||
532 | |||
533 | out_free: | ||
534 | free_memtype(start, end); | ||
535 | ret = -EBUSY; | ||
536 | out_err: | ||
537 | return ret; | ||
538 | } | ||
539 | |||
540 | /** | ||
541 | * io_free_memtype - Release a memory type mapping for a region of memory | ||
542 | * @start: start (physical address) of the region | ||
543 | * @end: end (physical address) of the region | ||
544 | */ | ||
545 | void io_free_memtype(resource_size_t start, resource_size_t end) | ||
546 | { | ||
547 | free_memtype(start, end); | ||
548 | } | ||
549 | |||
501 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 550 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
502 | unsigned long size, pgprot_t vma_prot) | 551 | unsigned long size, pgprot_t vma_prot) |
503 | { | 552 | { |