From e22e0a3bfedc5112a755286f89d21d9fe71bbc31 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 7 Dec 2011 12:24:42 +0100 Subject: [PATCH] --- yaml --- r: 282795 b: refs/heads/master c: bc21662f729cd17d2af93e149f4eccafc7b10181 h: refs/heads/master i: 282793: 0ff812c07d3a6b804136d418505e49e57a91167a 282791: b58f73c1c9a20d1f8d59b90bf0a8d312cb8c73f7 v: v3 --- [refs] | 2 +- trunk/drivers/iommu/amd_iommu_v2.c | 35 ++++++++++++++++++++++++++++++ trunk/include/linux/amd-iommu.h | 17 +++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index b21920c15d71..2d6f6dc2b844 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 52efdb89d60a0f19949129a08af3437a7aab70be +refs/heads/master: bc21662f729cd17d2af93e149f4eccafc7b10181 diff --git a/trunk/drivers/iommu/amd_iommu_v2.c b/trunk/drivers/iommu/amd_iommu_v2.c index fe812e2a0474..8add9f125d3e 100644 --- a/trunk/drivers/iommu/amd_iommu_v2.c +++ b/trunk/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 @@ static int task_exit(struct notifier_block *nb, unsigned long e, void *data) 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 @@ int amd_iommu_set_invalid_ppr_cb(struct pci_dev *pdev, } 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/trunk/include/linux/amd-iommu.h b/trunk/include/linux/amd-iommu.h index c03c281ae6ee..ef00610837d4 100644 --- a/trunk/include/linux/amd-iommu.h +++ b/trunk/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; }