diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 16:00:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 16:00:36 -0500 |
commit | 78a45c6f067824cf5d0a9fedea7339ac2e28603c (patch) | |
tree | b4f78c8b6b9059ddace0a18c11629b8d2045f793 /drivers/iommu/amd_iommu_v2.c | |
parent | f96fe225677b3efb74346ebd56fafe3997b02afa (diff) | |
parent | 29d293b6007b91a4463f05bc8d0b26e0e65c5816 (diff) |
Merge branch 'akpm' (second patch-bomb from Andrew)
Merge second patchbomb from Andrew Morton:
- the rest of MM
- misc fs fixes
- add execveat() syscall
- new ratelimit feature for fault-injection
- decompressor updates
- ipc/ updates
- fallocate feature creep
- fsnotify cleanups
- a few other misc things
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (99 commits)
cgroups: Documentation: fix trivial typos and wrong paragraph numberings
parisc: percpu: update comments referring to __get_cpu_var
percpu: update local_ops.txt to reflect this_cpu operations
percpu: remove __get_cpu_var and __raw_get_cpu_var macros
fsnotify: remove destroy_list from fsnotify_mark
fsnotify: unify inode and mount marks handling
fallocate: create FAN_MODIFY and IN_MODIFY events
mm/cma: make kmemleak ignore CMA regions
slub: fix cpuset check in get_any_partial
slab: fix cpuset check in fallback_alloc
shmdt: use i_size_read() instead of ->i_size
ipc/shm.c: fix overly aggressive shmdt() when calls span multiple segments
ipc/msg: increase MSGMNI, remove scaling
ipc/sem.c: increase SEMMSL, SEMMNI, SEMOPM
ipc/sem.c: change memory barrier in sem_lock() to smp_rmb()
lib/decompress.c: consistency of compress formats for kernel image
decompress_bunzip2: off by one in get_next_block()
usr/Kconfig: make initrd compression algorithm selection not expert
fault-inject: add ratelimit option
ratelimit: add initialization macro
...
Diffstat (limited to 'drivers/iommu/amd_iommu_v2.c')
-rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 84 |
1 files changed, 53 insertions, 31 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index a2d87a60c27f..bea878f8e7d3 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
@@ -509,45 +509,67 @@ static void finish_pri_tag(struct device_state *dev_state, | |||
509 | spin_unlock_irqrestore(&pasid_state->lock, flags); | 509 | spin_unlock_irqrestore(&pasid_state->lock, flags); |
510 | } | 510 | } |
511 | 511 | ||
512 | static void handle_fault_error(struct fault *fault) | ||
513 | { | ||
514 | int status; | ||
515 | |||
516 | if (!fault->dev_state->inv_ppr_cb) { | ||
517 | set_pri_tag_status(fault->state, fault->tag, PPR_INVALID); | ||
518 | return; | ||
519 | } | ||
520 | |||
521 | status = fault->dev_state->inv_ppr_cb(fault->dev_state->pdev, | ||
522 | fault->pasid, | ||
523 | fault->address, | ||
524 | fault->flags); | ||
525 | switch (status) { | ||
526 | case AMD_IOMMU_INV_PRI_RSP_SUCCESS: | ||
527 | set_pri_tag_status(fault->state, fault->tag, PPR_SUCCESS); | ||
528 | break; | ||
529 | case AMD_IOMMU_INV_PRI_RSP_INVALID: | ||
530 | set_pri_tag_status(fault->state, fault->tag, PPR_INVALID); | ||
531 | break; | ||
532 | case AMD_IOMMU_INV_PRI_RSP_FAIL: | ||
533 | set_pri_tag_status(fault->state, fault->tag, PPR_FAILURE); | ||
534 | break; | ||
535 | default: | ||
536 | BUG(); | ||
537 | } | ||
538 | } | ||
539 | |||
512 | static void do_fault(struct work_struct *work) | 540 | static void do_fault(struct work_struct *work) |
513 | { | 541 | { |
514 | struct fault *fault = container_of(work, struct fault, work); | 542 | struct fault *fault = container_of(work, struct fault, work); |
515 | int npages, write; | 543 | struct mm_struct *mm; |
516 | struct page *page; | 544 | struct vm_area_struct *vma; |
545 | u64 address; | ||
546 | int ret, write; | ||
517 | 547 | ||
518 | write = !!(fault->flags & PPR_FAULT_WRITE); | 548 | write = !!(fault->flags & PPR_FAULT_WRITE); |
519 | 549 | ||
520 | down_read(&fault->state->mm->mmap_sem); | 550 | mm = fault->state->mm; |
521 | npages = get_user_pages(NULL, fault->state->mm, | 551 | address = fault->address; |
522 | fault->address, 1, write, 0, &page, NULL); | 552 | |
523 | up_read(&fault->state->mm->mmap_sem); | 553 | down_read(&mm->mmap_sem); |
524 | 554 | vma = find_extend_vma(mm, address); | |
525 | if (npages == 1) { | 555 | if (!vma || address < vma->vm_start) { |
526 | put_page(page); | 556 | /* failed to get a vma in the right range */ |
527 | } else if (fault->dev_state->inv_ppr_cb) { | 557 | up_read(&mm->mmap_sem); |
528 | int status; | 558 | handle_fault_error(fault); |
529 | 559 | goto out; | |
530 | status = fault->dev_state->inv_ppr_cb(fault->dev_state->pdev, | 560 | } |
531 | fault->pasid, | 561 | |
532 | fault->address, | 562 | ret = handle_mm_fault(mm, vma, address, write); |
533 | fault->flags); | 563 | if (ret & VM_FAULT_ERROR) { |
534 | switch (status) { | 564 | /* failed to service fault */ |
535 | case AMD_IOMMU_INV_PRI_RSP_SUCCESS: | 565 | up_read(&mm->mmap_sem); |
536 | set_pri_tag_status(fault->state, fault->tag, PPR_SUCCESS); | 566 | handle_fault_error(fault); |
537 | break; | 567 | goto out; |
538 | case AMD_IOMMU_INV_PRI_RSP_INVALID: | ||
539 | set_pri_tag_status(fault->state, fault->tag, PPR_INVALID); | ||
540 | break; | ||
541 | case AMD_IOMMU_INV_PRI_RSP_FAIL: | ||
542 | set_pri_tag_status(fault->state, fault->tag, PPR_FAILURE); | ||
543 | break; | ||
544 | default: | ||
545 | BUG(); | ||
546 | } | ||
547 | } else { | ||
548 | set_pri_tag_status(fault->state, fault->tag, PPR_INVALID); | ||
549 | } | 568 | } |
550 | 569 | ||
570 | up_read(&mm->mmap_sem); | ||
571 | |||
572 | out: | ||
551 | finish_pri_tag(fault->dev_state, fault->state, fault->tag); | 573 | finish_pri_tag(fault->dev_state, fault->state, fault->tag); |
552 | 574 | ||
553 | put_pasid_state(fault->state); | 575 | put_pasid_state(fault->state); |