diff options
author | Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> | 2020-09-23 12:13:45 +0000 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2020-09-24 12:46:40 +0200 |
commit | c69d89aff393a212b9635c95990173b48d8bd74d (patch) | |
tree | ced76feea84d5b77c86ba4267b1b48f069dea2e4 /drivers/iommu/amd/init.c | |
parent | 06ce8a62ce81f47542043d93b64a4be106e98106 (diff) |
iommu/amd: Use 4K page for completion wait write-back semaphore
IOMMU SNP support requires the completion wait write-back semaphore to be
implemented using a 4K-aligned page, where the page address is to be
programmed into the newly introduced MMIO base/range registers.
This new scheme uses a per-iommu atomic variable to store the current
semaphore value, which is incremented for every completion wait command.
Since this new scheme is also compatible with non-SNP mode,
generalize the driver to use 4K page for completion-wait semaphore in
both modes.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Link: https://lore.kernel.org/r/20200923121347.25365-2-suravee.suthikulpanit@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd/init.c')
-rw-r--r-- | drivers/iommu/amd/init.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 908d8e89764c..35f220704bef 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -813,6 +813,19 @@ static int iommu_init_ga(struct amd_iommu *iommu) return ret; } +static int __init alloc_cwwb_sem(struct amd_iommu *iommu) +{ + iommu->cmd_sem = (void *)get_zeroed_page(GFP_KERNEL); + + return iommu->cmd_sem ? 0 : -ENOMEM; +} + +static void __init free_cwwb_sem(struct amd_iommu *iommu) +{ + if (iommu->cmd_sem) + free_page((unsigned long)iommu->cmd_sem); +} + static void iommu_enable_xt(struct amd_iommu *iommu) { #ifdef CONFIG_IRQ_REMAP @@ -1395,6 +1408,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, static void __init free_iommu_one(struct amd_iommu *iommu) { + free_cwwb_sem(iommu); free_command_buffer(iommu); free_event_buffer(iommu); free_ppr_log(iommu); @@ -1481,6 +1495,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) int ret; raw_spin_lock_init(&iommu->lock); + iommu->cmd_sem_val = 0; /* Add IOMMU to internal data structures */ list_add_tail(&iommu->list, &amd_iommu_list); @@ -1541,6 +1556,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->mmio_base) return -ENOMEM; + if (alloc_cwwb_sem(iommu)) + return -ENOMEM; + if (alloc_command_buffer(iommu)) return -ENOMEM; |