diff options
| -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 | { |
