mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-05-26 11:40:24 +02:00
iommu/amd: Use ida interface to manage protection domain ID
Replace custom domain ID allocator with IDA interface. Signed-off-by: Vasant Hegde <vasant.hegde@amd.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/20241030063556.6104-3-vasant.hegde@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
committed by
Joerg Roedel
parent
016991606a
commit
2fcab2deeb
@@ -912,14 +912,14 @@ struct unity_map_entry {
|
||||
/* size of the dma_ops aperture as power of 2 */
|
||||
extern unsigned amd_iommu_aperture_order;
|
||||
|
||||
/* allocation bitmap for domain ids */
|
||||
extern unsigned long *amd_iommu_pd_alloc_bitmap;
|
||||
|
||||
extern bool amd_iommu_force_isolation;
|
||||
|
||||
/* Max levels of glxval supported */
|
||||
extern int amd_iommu_max_glx_val;
|
||||
|
||||
/* IDA to track protection domain IDs */
|
||||
extern struct ida pdom_ids;
|
||||
|
||||
/* Global EFR and EFR2 registers */
|
||||
extern u64 amd_iommu_efr;
|
||||
extern u64 amd_iommu_efr2;
|
||||
|
||||
@@ -194,12 +194,6 @@ bool amd_iommu_force_isolation __read_mostly;
|
||||
|
||||
unsigned long amd_iommu_pgsize_bitmap __ro_after_init = AMD_IOMMU_PGSIZES;
|
||||
|
||||
/*
|
||||
* AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
|
||||
* to know which ones are already in use.
|
||||
*/
|
||||
unsigned long *amd_iommu_pd_alloc_bitmap;
|
||||
|
||||
enum iommu_init_state {
|
||||
IOMMU_START_STATE,
|
||||
IOMMU_IVRS_DETECTED,
|
||||
@@ -1082,7 +1076,12 @@ static bool __copy_device_table(struct amd_iommu *iommu)
|
||||
if (dte_v && dom_id) {
|
||||
pci_seg->old_dev_tbl_cpy[devid].data[0] = old_devtb[devid].data[0];
|
||||
pci_seg->old_dev_tbl_cpy[devid].data[1] = old_devtb[devid].data[1];
|
||||
__set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
|
||||
/* Reserve the Domain IDs used by previous kernel */
|
||||
if (ida_alloc_range(&pdom_ids, dom_id, dom_id, GFP_ATOMIC) != dom_id) {
|
||||
pr_err("Failed to reserve domain ID 0x%x\n", dom_id);
|
||||
memunmap(old_devtb);
|
||||
return false;
|
||||
}
|
||||
/* If gcr3 table existed, mask it out */
|
||||
if (old_devtb[devid].data[0] & DTE_FLAG_GV) {
|
||||
tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
|
||||
@@ -2985,9 +2984,7 @@ static bool __init check_ioapic_information(void)
|
||||
|
||||
static void __init free_dma_resources(void)
|
||||
{
|
||||
iommu_free_pages(amd_iommu_pd_alloc_bitmap,
|
||||
get_order(MAX_DOMAIN_ID / 8));
|
||||
amd_iommu_pd_alloc_bitmap = NULL;
|
||||
ida_destroy(&pdom_ids);
|
||||
|
||||
free_unity_maps();
|
||||
}
|
||||
@@ -3055,20 +3052,6 @@ static int __init early_amd_iommu_init(void)
|
||||
amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base);
|
||||
DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type);
|
||||
|
||||
/* Device table - directly used by all IOMMUs */
|
||||
ret = -ENOMEM;
|
||||
|
||||
amd_iommu_pd_alloc_bitmap = iommu_alloc_pages(GFP_KERNEL,
|
||||
get_order(MAX_DOMAIN_ID / 8));
|
||||
if (amd_iommu_pd_alloc_bitmap == NULL)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* never allocate domain 0 because its used as the non-allocated and
|
||||
* error value placeholder
|
||||
*/
|
||||
__set_bit(0, amd_iommu_pd_alloc_bitmap);
|
||||
|
||||
/*
|
||||
* now the data structures are allocated and basically initialized
|
||||
* start the real acpi table scan
|
||||
|
||||
+25
-31
@@ -18,6 +18,7 @@
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/dma-direct.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/iommu-helper.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/amd-iommu.h>
|
||||
@@ -52,8 +53,6 @@
|
||||
#define HT_RANGE_START (0xfd00000000ULL)
|
||||
#define HT_RANGE_END (0xffffffffffULL)
|
||||
|
||||
static DEFINE_SPINLOCK(pd_bitmap_lock);
|
||||
|
||||
LIST_HEAD(ioapic_map);
|
||||
LIST_HEAD(hpet_map);
|
||||
LIST_HEAD(acpihid_map);
|
||||
@@ -70,6 +69,12 @@ struct iommu_cmd {
|
||||
u32 data[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
|
||||
* to know which ones are already in use.
|
||||
*/
|
||||
DEFINE_IDA(pdom_ids);
|
||||
|
||||
struct kmem_cache *amd_iommu_irq_cache;
|
||||
|
||||
static void detach_device(struct device *dev);
|
||||
@@ -1643,31 +1648,14 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static u16 domain_id_alloc(void)
|
||||
static int pdom_id_alloc(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&pd_bitmap_lock, flags);
|
||||
id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
|
||||
BUG_ON(id == 0);
|
||||
if (id > 0 && id < MAX_DOMAIN_ID)
|
||||
__set_bit(id, amd_iommu_pd_alloc_bitmap);
|
||||
else
|
||||
id = 0;
|
||||
spin_unlock_irqrestore(&pd_bitmap_lock, flags);
|
||||
|
||||
return id;
|
||||
return ida_alloc_range(&pdom_ids, 1, MAX_DOMAIN_ID - 1, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static void domain_id_free(int id)
|
||||
static void pdom_id_free(int id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pd_bitmap_lock, flags);
|
||||
if (id > 0 && id < MAX_DOMAIN_ID)
|
||||
__clear_bit(id, amd_iommu_pd_alloc_bitmap);
|
||||
spin_unlock_irqrestore(&pd_bitmap_lock, flags);
|
||||
ida_free(&pdom_ids, id);
|
||||
}
|
||||
|
||||
static void free_gcr3_tbl_level1(u64 *tbl)
|
||||
@@ -1712,7 +1700,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
|
||||
gcr3_info->glx = 0;
|
||||
|
||||
/* Free per device domain ID */
|
||||
domain_id_free(gcr3_info->domid);
|
||||
pdom_id_free(gcr3_info->domid);
|
||||
|
||||
iommu_free_page(gcr3_info->gcr3_tbl);
|
||||
gcr3_info->gcr3_tbl = NULL;
|
||||
@@ -1739,6 +1727,7 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
|
||||
{
|
||||
int levels = get_gcr3_levels(pasids);
|
||||
int nid = iommu ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
|
||||
int domid;
|
||||
|
||||
if (levels > amd_iommu_max_glx_val)
|
||||
return -EINVAL;
|
||||
@@ -1747,11 +1736,14 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
|
||||
return -EBUSY;
|
||||
|
||||
/* Allocate per device domain ID */
|
||||
gcr3_info->domid = domain_id_alloc();
|
||||
domid = pdom_id_alloc();
|
||||
if (domid <= 0)
|
||||
return -ENOSPC;
|
||||
gcr3_info->domid = domid;
|
||||
|
||||
gcr3_info->gcr3_tbl = iommu_alloc_page_node(nid, GFP_ATOMIC);
|
||||
if (gcr3_info->gcr3_tbl == NULL) {
|
||||
domain_id_free(gcr3_info->domid);
|
||||
pdom_id_free(domid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -2262,7 +2254,7 @@ void protection_domain_free(struct protection_domain *domain)
|
||||
WARN_ON(!list_empty(&domain->dev_list));
|
||||
if (domain->domain.type & __IOMMU_DOMAIN_PAGING)
|
||||
free_io_pgtable_ops(&domain->iop.pgtbl.ops);
|
||||
domain_id_free(domain->id);
|
||||
pdom_id_free(domain->id);
|
||||
kfree(domain);
|
||||
}
|
||||
|
||||
@@ -2277,16 +2269,18 @@ static void protection_domain_init(struct protection_domain *domain, int nid)
|
||||
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
|
||||
{
|
||||
struct protection_domain *domain;
|
||||
int domid;
|
||||
|
||||
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
|
||||
if (!domain)
|
||||
return NULL;
|
||||
|
||||
domain->id = domain_id_alloc();
|
||||
if (!domain->id) {
|
||||
domid = pdom_id_alloc();
|
||||
if (domid <= 0) {
|
||||
kfree(domain);
|
||||
return NULL;
|
||||
}
|
||||
domain->id = domid;
|
||||
|
||||
protection_domain_init(domain, nid);
|
||||
|
||||
@@ -2361,7 +2355,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
|
||||
|
||||
ret = pdom_setup_pgtable(domain, type, pgtable);
|
||||
if (ret) {
|
||||
domain_id_free(domain->id);
|
||||
pdom_id_free(domain->id);
|
||||
kfree(domain);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@@ -2493,7 +2487,7 @@ void amd_iommu_init_identity_domain(void)
|
||||
domain->ops = &identity_domain_ops;
|
||||
domain->owner = &amd_iommu_ops;
|
||||
|
||||
identity_domain.id = domain_id_alloc();
|
||||
identity_domain.id = pdom_id_alloc();
|
||||
|
||||
protection_domain_init(&identity_domain, NUMA_NO_NODE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user