Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'iommu-fixes-v3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull IOMMU fixes from Joerg Roedel:

- fix VT-d regression with handling multiple RMRR entries per device

- fix a small race that was left in the mmu_notifier handling in the
AMD IOMMUv2 driver

* tag 'iommu-fixes-v3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
iommu/amd: Fix small race between invalidate_range_end/start
iommu/vt-d: fix bug in handling multiple RMRRs for the same PCI device

+16 -11
+13 -5
drivers/iommu/amd_iommu_v2.c
··· 45 45 struct pasid_state { 46 46 struct list_head list; /* For global state-list */ 47 47 atomic_t count; /* Reference count */ 48 - atomic_t mmu_notifier_count; /* Counting nested mmu_notifier 48 + unsigned mmu_notifier_count; /* Counting nested mmu_notifier 49 49 calls */ 50 50 struct task_struct *task; /* Task bound to this PASID */ 51 51 struct mm_struct *mm; /* mm_struct for the faults */ ··· 53 53 struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */ 54 54 struct device_state *device_state; /* Link to our device_state */ 55 55 int pasid; /* PASID index */ 56 - spinlock_t lock; /* Protect pri_queues */ 56 + spinlock_t lock; /* Protect pri_queues and 57 + mmu_notifer_count */ 57 58 wait_queue_head_t wq; /* To wait for count == 0 */ 58 59 }; 59 60 ··· 432 431 { 433 432 struct pasid_state *pasid_state; 434 433 struct device_state *dev_state; 434 + unsigned long flags; 435 435 436 436 pasid_state = mn_to_state(mn); 437 437 dev_state = pasid_state->device_state; 438 438 439 - if (atomic_add_return(1, &pasid_state->mmu_notifier_count) == 1) { 439 + spin_lock_irqsave(&pasid_state->lock, flags); 440 + if (pasid_state->mmu_notifier_count == 0) { 440 441 amd_iommu_domain_set_gcr3(dev_state->domain, 441 442 pasid_state->pasid, 442 443 __pa(empty_page_table)); 443 444 } 445 + pasid_state->mmu_notifier_count += 1; 446 + spin_unlock_irqrestore(&pasid_state->lock, flags); 444 447 } 445 448 446 449 static void mn_invalidate_range_end(struct mmu_notifier *mn, ··· 453 448 { 454 449 struct pasid_state *pasid_state; 455 450 struct device_state *dev_state; 451 + unsigned long flags; 456 452 457 453 pasid_state = mn_to_state(mn); 458 454 dev_state = pasid_state->device_state; 459 455 460 - if (atomic_dec_and_test(&pasid_state->mmu_notifier_count)) { 456 + spin_lock_irqsave(&pasid_state->lock, flags); 457 + pasid_state->mmu_notifier_count -= 1; 458 + if (pasid_state->mmu_notifier_count == 0) { 461 459 amd_iommu_domain_set_gcr3(dev_state->domain, 462 460 pasid_state->pasid, 463 461 __pa(pasid_state->mm->pgd)); 464 462 } 463 + spin_unlock_irqrestore(&pasid_state->lock, flags); 465 464 } 466 465 467 466 static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm) ··· 659 650 goto out; 660 651 661 652 atomic_set(&pasid_state->count, 1); 662 - atomic_set(&pasid_state->mmu_notifier_count, 0); 663 653 init_waitqueue_head(&pasid_state->wq); 664 654 spin_lock_init(&pasid_state->lock); 665 655
+3 -6
drivers/iommu/intel-iommu.c
··· 3816 3816 ((void *)rmrr) + rmrr->header.length, 3817 3817 rmrr->segment, rmrru->devices, 3818 3818 rmrru->devices_cnt); 3819 - if (ret > 0) 3820 - break; 3821 - else if(ret < 0) 3819 + if(ret < 0) 3822 3820 return ret; 3823 3821 } else if (info->event == BUS_NOTIFY_DEL_DEVICE) { 3824 - if (dmar_remove_dev_scope(info, rmrr->segment, 3825 - rmrru->devices, rmrru->devices_cnt)) 3826 - break; 3822 + dmar_remove_dev_scope(info, rmrr->segment, 3823 + rmrru->devices, rmrru->devices_cnt); 3827 3824 } 3828 3825 } 3829 3826