diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index fe812e2a0474..8add9f125d3e 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -63,6 +63,7 @@ struct device_state { int pasid_levels; int max_pasids; amd_iommu_invalid_ppr_cb inv_ppr_cb; + amd_iommu_invalidate_ctx inv_ctx_cb; spinlock_t lock; wait_queue_head_t wq; }; @@ -637,6 +638,9 @@ again: dev_state = pasid_state->device_state; pasid = pasid_state->pasid; + if (pasid_state->device_state->inv_ctx_cb) + dev_state->inv_ctx_cb(dev_state->pdev, pasid); + unbind_pasid(dev_state, pasid); /* Task may be in the list multiple times */ @@ -881,6 +885,37 @@ out_unlock: } EXPORT_SYMBOL(amd_iommu_set_invalid_ppr_cb); +int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, + amd_iommu_invalidate_ctx cb) +{ + struct device_state *dev_state; + unsigned long flags; + u16 devid; + int ret; + + if (!amd_iommu_v2_supported()) + return -ENODEV; + + devid = device_id(pdev); + + spin_lock_irqsave(&state_lock, flags); + + ret = -EINVAL; + dev_state = state_table[devid]; + if (dev_state == NULL) + goto out_unlock; + + dev_state->inv_ctx_cb = cb; + + ret = 0; + +out_unlock: + spin_unlock_irqrestore(&state_lock, flags); + + return ret; +} +EXPORT_SYMBOL(amd_iommu_set_invalidate_ctx_cb); + static int __init amd_iommu_v2_init(void) { size_t state_table_size; |