diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-07 12:24:42 +0100 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-15 11:15:39 +0100 |
commit | bc21662f729cd17d2af93e149f4eccafc7b10181 (patch) | |
tree | cb980b6412dc1b42383fefe9898c808167d4a4c6 | |
parent | iommu/amd: Add amd_iommu_device_info() function (diff) | |
download | linux-bc21662f729cd17d2af93e149f4eccafc7b10181.tar.xz linux-bc21662f729cd17d2af93e149f4eccafc7b10181.zip |
iommu/amd: Add invalidate-context call-back
This call-back is invoked when the task that is bound to a
pasid is about to exit. The driver can use it to shutdown
all context related to that context in a safe way.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 35 | ||||
-rw-r--r-- | include/linux/amd-iommu.h | 17 |
2 files changed, 52 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; diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index c03c281ae6ee..ef00610837d4 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h @@ -145,6 +145,23 @@ struct amd_iommu_device_info { extern int amd_iommu_device_info(struct pci_dev *pdev, struct amd_iommu_device_info *info); +/** + * amd_iommu_set_invalidate_ctx_cb() - Register a call-back for invalidating + * a pasid context. This call-back is + * invoked when the IOMMUv2 driver needs to + * invalidate a PASID context, for example + * because the task that is bound to that + * context is about to exit. + * + * @pdev: The PCI device the call-back should be registered for + * @cb: The call-back function + */ + +typedef void (*amd_iommu_invalidate_ctx)(struct pci_dev *pdev, int pasid); + +extern int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, + amd_iommu_invalidate_ctx cb); + #else static inline int amd_iommu_detect(void) { return -ENODEV; } |