1818#include <linux/scatterlist.h>
1919#include <linux/dma-map-ops.h>
2020#include <linux/dma-direct.h>
21+ #include <linux/idr.h>
2122#include <linux/iommu-helper.h>
2223#include <linux/delay.h>
2324#include <linux/amd-iommu.h>
5253#define HT_RANGE_START (0xfd00000000ULL)
5354#define HT_RANGE_END (0xffffffffffULL)
5455
55- static DEFINE_SPINLOCK (pd_bitmap_lock );
56-
5756LIST_HEAD (ioapic_map );
5857LIST_HEAD (hpet_map );
5958LIST_HEAD (acpihid_map );
@@ -70,6 +69,12 @@ struct iommu_cmd {
7069 u32 data [4 ];
7170};
7271
72+ /*
73+ * AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
74+ * to know which ones are already in use.
75+ */
76+ DEFINE_IDA (pdom_ids );
77+
7378struct kmem_cache * amd_iommu_irq_cache ;
7479
7580static void detach_device (struct device * dev );
@@ -1643,31 +1648,14 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
16431648 *
16441649 ****************************************************************************/
16451650
1646- static u16 domain_id_alloc (void )
1651+ static int pdom_id_alloc (void )
16471652{
1648- unsigned long flags ;
1649- int id ;
1650-
1651- spin_lock_irqsave (& pd_bitmap_lock , flags );
1652- id = find_first_zero_bit (amd_iommu_pd_alloc_bitmap , MAX_DOMAIN_ID );
1653- BUG_ON (id == 0 );
1654- if (id > 0 && id < MAX_DOMAIN_ID )
1655- __set_bit (id , amd_iommu_pd_alloc_bitmap );
1656- else
1657- id = 0 ;
1658- spin_unlock_irqrestore (& pd_bitmap_lock , flags );
1659-
1660- return id ;
1653+ return ida_alloc_range (& pdom_ids , 1 , MAX_DOMAIN_ID - 1 , GFP_ATOMIC );
16611654}
16621655
1663- static void domain_id_free (int id )
1656+ static void pdom_id_free (int id )
16641657{
1665- unsigned long flags ;
1666-
1667- spin_lock_irqsave (& pd_bitmap_lock , flags );
1668- if (id > 0 && id < MAX_DOMAIN_ID )
1669- __clear_bit (id , amd_iommu_pd_alloc_bitmap );
1670- spin_unlock_irqrestore (& pd_bitmap_lock , flags );
1658+ ida_free (& pdom_ids , id );
16711659}
16721660
16731661static void free_gcr3_tbl_level1 (u64 * tbl )
@@ -1712,7 +1700,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
17121700 gcr3_info -> glx = 0 ;
17131701
17141702 /* Free per device domain ID */
1715- domain_id_free (gcr3_info -> domid );
1703+ pdom_id_free (gcr3_info -> domid );
17161704
17171705 iommu_free_page (gcr3_info -> gcr3_tbl );
17181706 gcr3_info -> gcr3_tbl = NULL ;
@@ -1739,6 +1727,7 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
17391727{
17401728 int levels = get_gcr3_levels (pasids );
17411729 int nid = iommu ? dev_to_node (& iommu -> dev -> dev ) : NUMA_NO_NODE ;
1730+ int domid ;
17421731
17431732 if (levels > amd_iommu_max_glx_val )
17441733 return - EINVAL ;
@@ -1747,11 +1736,14 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
17471736 return - EBUSY ;
17481737
17491738 /* Allocate per device domain ID */
1750- gcr3_info -> domid = domain_id_alloc ();
1739+ domid = pdom_id_alloc ();
1740+ if (domid <= 0 )
1741+ return - ENOSPC ;
1742+ gcr3_info -> domid = domid ;
17511743
17521744 gcr3_info -> gcr3_tbl = iommu_alloc_page_node (nid , GFP_ATOMIC );
17531745 if (gcr3_info -> gcr3_tbl == NULL ) {
1754- domain_id_free ( gcr3_info -> domid );
1746+ pdom_id_free ( domid );
17551747 return - ENOMEM ;
17561748 }
17571749
@@ -2262,7 +2254,7 @@ void protection_domain_free(struct protection_domain *domain)
22622254 WARN_ON (!list_empty (& domain -> dev_list ));
22632255 if (domain -> domain .type & __IOMMU_DOMAIN_PAGING )
22642256 free_io_pgtable_ops (& domain -> iop .pgtbl .ops );
2265- domain_id_free (domain -> id );
2257+ pdom_id_free (domain -> id );
22662258 kfree (domain );
22672259}
22682260
@@ -2277,16 +2269,18 @@ static void protection_domain_init(struct protection_domain *domain, int nid)
22772269struct protection_domain * protection_domain_alloc (unsigned int type , int nid )
22782270{
22792271 struct protection_domain * domain ;
2272+ int domid ;
22802273
22812274 domain = kzalloc (sizeof (* domain ), GFP_KERNEL );
22822275 if (!domain )
22832276 return NULL ;
22842277
2285- domain -> id = domain_id_alloc ();
2286- if (! domain -> id ) {
2278+ domid = pdom_id_alloc ();
2279+ if (domid <= 0 ) {
22872280 kfree (domain );
22882281 return NULL ;
22892282 }
2283+ domain -> id = domid ;
22902284
22912285 protection_domain_init (domain , nid );
22922286
@@ -2361,7 +2355,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
23612355
23622356 ret = pdom_setup_pgtable (domain , type , pgtable );
23632357 if (ret ) {
2364- domain_id_free (domain -> id );
2358+ pdom_id_free (domain -> id );
23652359 kfree (domain );
23662360 return ERR_PTR (ret );
23672361 }
@@ -2493,7 +2487,7 @@ void amd_iommu_init_identity_domain(void)
24932487 domain -> ops = & identity_domain_ops ;
24942488 domain -> owner = & amd_iommu_ops ;
24952489
2496- identity_domain .id = domain_id_alloc ();
2490+ identity_domain .id = pdom_id_alloc ();
24972491
24982492 protection_domain_init (& identity_domain , NUMA_NO_NODE );
24992493}
0 commit comments