IOMMU Fixes for Linux v3.16-rc1
* 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTqTeIAAoJECvwRC2XARrjL0gQAMLPRDWaXPsVxlq3pAMb+My4 AzqB5jBWV4sNNt/jg/qa81FI6MvDknkNlAO2iCJa71nBnuGQFD6V9Rwp5wzWTJpe M29UV3ZDaUgH6ox3oPHUtnNtsSJhJ8E23qL/q5gBPIL8eM21Gworau/CkNfGf3DA K/ut3KhyqHHcGlST27CAKwH2QyvcdXOpwL4xLLB1buv3SWW2EjVqeXA8c5YqybQy a9ucoLKp8MrosTvrzSYgZzYfOJCaSpzfVwEC2G2Hrh2IHdrRNE5GcFu07qrR2cLC 1QKBVaCgK5PSPQAd8fhg0lfwzIUPi0ZrxjPhdQlG+E+V1SNFU5tcVdn0p8TmljLN 3vGdRS90o3XM2pkdv6h1pkzEd6aukBw5LkORYcMJwDEn40S2lSYW2za+sOkyAltH jgHDQDtRCMnJpj7fa6x5Nk3VkWBRbdpuyJLPmqzMwhUzGq1FUrM1PSIo9962u3nk BhRP0A5/emaH/Fc94S+sspfOHYVnpqr/wtRrMln7xbIrKSxyQh3MX9J7vHxpw/Wl qWGYFV4RfG+JT9dGF+SAZTVFLTpgnh32gpKHJgUkahAyxHQVuckmk99XD1ScpDCD fArbvL+SCo/i35aScAvzP0+lXJggfeaeslGKPHQx8FLY+zrV2krYEBh3hBlXibJT turjVNs8gAwE6uzp1+Cv =ZWyp -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
3e7b256cba
2 changed files with 16 additions and 11 deletions
|
@ -45,7 +45,7 @@ struct pri_queue {
|
|||
struct pasid_state {
|
||||
struct list_head list; /* For global state-list */
|
||||
atomic_t count; /* Reference count */
|
||||
atomic_t mmu_notifier_count; /* Counting nested mmu_notifier
|
||||
unsigned mmu_notifier_count; /* Counting nested mmu_notifier
|
||||
calls */
|
||||
struct task_struct *task; /* Task bound to this PASID */
|
||||
struct mm_struct *mm; /* mm_struct for the faults */
|
||||
|
@ -53,7 +53,8 @@ struct pasid_state {
|
|||
struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */
|
||||
struct device_state *device_state; /* Link to our device_state */
|
||||
int pasid; /* PASID index */
|
||||
spinlock_t lock; /* Protect pri_queues */
|
||||
spinlock_t lock; /* Protect pri_queues and
|
||||
mmu_notifer_count */
|
||||
wait_queue_head_t wq; /* To wait for count == 0 */
|
||||
};
|
||||
|
||||
|
@ -431,15 +432,19 @@ static void mn_invalidate_range_start(struct mmu_notifier *mn,
|
|||
{
|
||||
struct pasid_state *pasid_state;
|
||||
struct device_state *dev_state;
|
||||
unsigned long flags;
|
||||
|
||||
pasid_state = mn_to_state(mn);
|
||||
dev_state = pasid_state->device_state;
|
||||
|
||||
if (atomic_add_return(1, &pasid_state->mmu_notifier_count) == 1) {
|
||||
spin_lock_irqsave(&pasid_state->lock, flags);
|
||||
if (pasid_state->mmu_notifier_count == 0) {
|
||||
amd_iommu_domain_set_gcr3(dev_state->domain,
|
||||
pasid_state->pasid,
|
||||
__pa(empty_page_table));
|
||||
}
|
||||
pasid_state->mmu_notifier_count += 1;
|
||||
spin_unlock_irqrestore(&pasid_state->lock, flags);
|
||||
}
|
||||
|
||||
static void mn_invalidate_range_end(struct mmu_notifier *mn,
|
||||
|
@ -448,15 +453,19 @@ static void mn_invalidate_range_end(struct mmu_notifier *mn,
|
|||
{
|
||||
struct pasid_state *pasid_state;
|
||||
struct device_state *dev_state;
|
||||
unsigned long flags;
|
||||
|
||||
pasid_state = mn_to_state(mn);
|
||||
dev_state = pasid_state->device_state;
|
||||
|
||||
if (atomic_dec_and_test(&pasid_state->mmu_notifier_count)) {
|
||||
spin_lock_irqsave(&pasid_state->lock, flags);
|
||||
pasid_state->mmu_notifier_count -= 1;
|
||||
if (pasid_state->mmu_notifier_count == 0) {
|
||||
amd_iommu_domain_set_gcr3(dev_state->domain,
|
||||
pasid_state->pasid,
|
||||
__pa(pasid_state->mm->pgd));
|
||||
}
|
||||
spin_unlock_irqrestore(&pasid_state->lock, flags);
|
||||
}
|
||||
|
||||
static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm)
|
||||
|
@ -650,7 +659,6 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
|
|||
goto out;
|
||||
|
||||
atomic_set(&pasid_state->count, 1);
|
||||
atomic_set(&pasid_state->mmu_notifier_count, 0);
|
||||
init_waitqueue_head(&pasid_state->wq);
|
||||
spin_lock_init(&pasid_state->lock);
|
||||
|
||||
|
|
|
@ -3816,14 +3816,11 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
|
|||
((void *)rmrr) + rmrr->header.length,
|
||||
rmrr->segment, rmrru->devices,
|
||||
rmrru->devices_cnt);
|
||||
if (ret > 0)
|
||||
break;
|
||||
else if(ret < 0)
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
} else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
|
||||
if (dmar_remove_dev_scope(info, rmrr->segment,
|
||||
rmrru->devices, rmrru->devices_cnt))
|
||||
break;
|
||||
dmar_remove_dev_scope(info, rmrr->segment,
|
||||
rmrru->devices, rmrru->devices_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue