diff options
| -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 { | |||
| 63 | int pasid_levels; | 63 | int pasid_levels; |
| 64 | int max_pasids; | 64 | int max_pasids; |
| 65 | amd_iommu_invalid_ppr_cb inv_ppr_cb; | 65 | amd_iommu_invalid_ppr_cb inv_ppr_cb; |
| 66 | amd_iommu_invalidate_ctx inv_ctx_cb; | ||
| 66 | spinlock_t lock; | 67 | spinlock_t lock; |
| 67 | wait_queue_head_t wq; | 68 | wait_queue_head_t wq; |
| 68 | }; | 69 | }; |
| @@ -637,6 +638,9 @@ again: | |||
| 637 | dev_state = pasid_state->device_state; | 638 | dev_state = pasid_state->device_state; |
| 638 | pasid = pasid_state->pasid; | 639 | pasid = pasid_state->pasid; |
| 639 | 640 | ||
| 641 | if (pasid_state->device_state->inv_ctx_cb) | ||
| 642 | dev_state->inv_ctx_cb(dev_state->pdev, pasid); | ||
| 643 | |||
| 640 | unbind_pasid(dev_state, pasid); | 644 | unbind_pasid(dev_state, pasid); |
| 641 | 645 | ||
| 642 | /* Task may be in the list multiple times */ | 646 | /* Task may be in the list multiple times */ |
| @@ -881,6 +885,37 @@ out_unlock: | |||
| 881 | } | 885 | } |
| 882 | EXPORT_SYMBOL(amd_iommu_set_invalid_ppr_cb); | 886 | EXPORT_SYMBOL(amd_iommu_set_invalid_ppr_cb); |
| 883 | 887 | ||
| 888 | int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, | ||
| 889 | amd_iommu_invalidate_ctx cb) | ||
| 890 | { | ||
| 891 | struct device_state *dev_state; | ||
| 892 | unsigned long flags; | ||
| 893 | u16 devid; | ||
| 894 | int ret; | ||
| 895 | |||
| 896 | if (!amd_iommu_v2_supported()) | ||
| 897 | return -ENODEV; | ||
| 898 | |||
| 899 | devid = device_id(pdev); | ||
| 900 | |||
| 901 | spin_lock_irqsave(&state_lock, flags); | ||
| 902 | |||
| 903 | ret = -EINVAL; | ||
| 904 | dev_state = state_table[devid]; | ||
| 905 | if (dev_state == NULL) | ||
| 906 | goto out_unlock; | ||
| 907 | |||
| 908 | dev_state->inv_ctx_cb = cb; | ||
| 909 | |||
| 910 | ret = 0; | ||
| 911 | |||
| 912 | out_unlock: | ||
| 913 | spin_unlock_irqrestore(&state_lock, flags); | ||
| 914 | |||
| 915 | return ret; | ||
| 916 | } | ||
| 917 | EXPORT_SYMBOL(amd_iommu_set_invalidate_ctx_cb); | ||
| 918 | |||
| 884 | static int __init amd_iommu_v2_init(void) | 919 | static int __init amd_iommu_v2_init(void) |
| 885 | { | 920 | { |
| 886 | size_t state_table_size; | 921 | 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 { | |||
| 145 | extern int amd_iommu_device_info(struct pci_dev *pdev, | 145 | extern int amd_iommu_device_info(struct pci_dev *pdev, |
| 146 | struct amd_iommu_device_info *info); | 146 | struct amd_iommu_device_info *info); |
| 147 | 147 | ||
| 148 | /** | ||
| 149 | * amd_iommu_set_invalidate_ctx_cb() - Register a call-back for invalidating | ||
| 150 | * a pasid context. This call-back is | ||
| 151 | * invoked when the IOMMUv2 driver needs to | ||
| 152 | * invalidate a PASID context, for example | ||
| 153 | * because the task that is bound to that | ||
| 154 | * context is about to exit. | ||
| 155 | * | ||
| 156 | * @pdev: The PCI device the call-back should be registered for | ||
| 157 | * @cb: The call-back function | ||
| 158 | */ | ||
| 159 | |||
| 160 | typedef void (*amd_iommu_invalidate_ctx)(struct pci_dev *pdev, int pasid); | ||
| 161 | |||
| 162 | extern int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, | ||
| 163 | amd_iommu_invalidate_ctx cb); | ||
| 164 | |||
| 148 | #else | 165 | #else |
| 149 | 166 | ||
| 150 | static inline int amd_iommu_detect(void) { return -ENODEV; } | 167 | static inline int amd_iommu_detect(void) { return -ENODEV; } |
