diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-07 06:24:42 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-15 05:15:39 -0500 |
commit | bc21662f729cd17d2af93e149f4eccafc7b10181 (patch) | |
tree | cb980b6412dc1b42383fefe9898c808167d4a4c6 | |
parent | 52efdb89d60a0f19949129a08af3437a7aab70be (diff) |
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 { | |||
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; } |