aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2014-05-20 17:18:23 -0400
committerJoerg Roedel <jroedel@suse.de>2014-05-26 05:28:12 -0400
commit741669c765c45cace9bd630f7c8c8047c8b33567 (patch)
tree9d8d9304cf6e58a9b43729e1a852250d526ca2d9 /drivers/iommu
parentb87d2d7c0b3507b6b17590d741b5be01e8a21b84 (diff)
iommu/amd: Convert IOMMUv2 state_table into state_list
The state_table consumes 512kb of memory and is only sparsly populated. Convert it into a list to save memory. There should be no measurable performance impact. Signed-off-by: Joerg Roedel <jroedel@suse.de> Tested-by: Jay Cornwall <Jay.Cornwall@amd.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu_v2.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 5db3675cad76..569b6a0b6f56 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -56,6 +56,8 @@ struct pasid_state {
56}; 56};
57 57
58struct device_state { 58struct device_state {
59 struct list_head list;
60 u16 devid;
59 atomic_t count; 61 atomic_t count;
60 struct pci_dev *pdev; 62 struct pci_dev *pdev;
61 struct pasid_state **states; 63 struct pasid_state **states;
@@ -81,7 +83,7 @@ struct fault {
81 u16 flags; 83 u16 flags;
82}; 84};
83 85
84static struct device_state **state_table; 86static LIST_HEAD(state_list);
85static spinlock_t state_lock; 87static spinlock_t state_lock;
86 88
87/* List and lock for all pasid_states */ 89/* List and lock for all pasid_states */
@@ -113,7 +115,14 @@ static u16 device_id(struct pci_dev *pdev)
113 115
114static struct device_state *__get_device_state(u16 devid) 116static struct device_state *__get_device_state(u16 devid)
115{ 117{
116 return state_table[devid]; 118 struct device_state *dev_state;
119
120 list_for_each_entry(dev_state, &state_list, list) {
121 if (dev_state->devid == devid)
122 return dev_state;
123 }
124
125 return NULL;
117} 126}
118 127
119static struct device_state *get_device_state(u16 devid) 128static struct device_state *get_device_state(u16 devid)
@@ -778,7 +787,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
778 787
779 spin_lock_init(&dev_state->lock); 788 spin_lock_init(&dev_state->lock);
780 init_waitqueue_head(&dev_state->wq); 789 init_waitqueue_head(&dev_state->wq);
781 dev_state->pdev = pdev; 790 dev_state->pdev = pdev;
791 dev_state->devid = devid;
782 792
783 tmp = pasids; 793 tmp = pasids;
784 for (dev_state->pasid_levels = 0; (tmp - 1) & ~0x1ff; tmp >>= 9) 794 for (dev_state->pasid_levels = 0; (tmp - 1) & ~0x1ff; tmp >>= 9)
@@ -808,13 +818,13 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
808 818
809 spin_lock_irqsave(&state_lock, flags); 819 spin_lock_irqsave(&state_lock, flags);
810 820
811 if (state_table[devid] != NULL) { 821 if (__get_device_state(devid) != NULL) {
812 spin_unlock_irqrestore(&state_lock, flags); 822 spin_unlock_irqrestore(&state_lock, flags);
813 ret = -EBUSY; 823 ret = -EBUSY;
814 goto out_free_domain; 824 goto out_free_domain;
815 } 825 }
816 826
817 state_table[devid] = dev_state; 827 list_add_tail(&dev_state->list, &state_list);
818 828
819 spin_unlock_irqrestore(&state_lock, flags); 829 spin_unlock_irqrestore(&state_lock, flags);
820 830
@@ -852,7 +862,7 @@ void amd_iommu_free_device(struct pci_dev *pdev)
852 return; 862 return;
853 } 863 }
854 864
855 state_table[devid] = NULL; 865 list_del(&dev_state->list);
856 866
857 spin_unlock_irqrestore(&state_lock, flags); 867 spin_unlock_irqrestore(&state_lock, flags);
858 868
@@ -927,7 +937,6 @@ EXPORT_SYMBOL(amd_iommu_set_invalidate_ctx_cb);
927 937
928static int __init amd_iommu_v2_init(void) 938static int __init amd_iommu_v2_init(void)
929{ 939{
930 size_t state_table_size;
931 int ret; 940 int ret;
932 941
933 pr_info("AMD IOMMUv2 driver by Joerg Roedel <joerg.roedel@amd.com>\n"); 942 pr_info("AMD IOMMUv2 driver by Joerg Roedel <joerg.roedel@amd.com>\n");
@@ -943,16 +952,10 @@ static int __init amd_iommu_v2_init(void)
943 952
944 spin_lock_init(&state_lock); 953 spin_lock_init(&state_lock);
945 954
946 state_table_size = MAX_DEVICES * sizeof(struct device_state *);
947 state_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
948 get_order(state_table_size));
949 if (state_table == NULL)
950 return -ENOMEM;
951
952 ret = -ENOMEM; 955 ret = -ENOMEM;
953 iommu_wq = create_workqueue("amd_iommu_v2"); 956 iommu_wq = create_workqueue("amd_iommu_v2");
954 if (iommu_wq == NULL) 957 if (iommu_wq == NULL)
955 goto out_free; 958 goto out;
956 959
957 ret = -ENOMEM; 960 ret = -ENOMEM;
958 empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL); 961 empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL);
@@ -967,16 +970,13 @@ static int __init amd_iommu_v2_init(void)
967out_destroy_wq: 970out_destroy_wq:
968 destroy_workqueue(iommu_wq); 971 destroy_workqueue(iommu_wq);
969 972
970out_free: 973out:
971 free_pages((unsigned long)state_table, get_order(state_table_size));
972
973 return ret; 974 return ret;
974} 975}
975 976
976static void __exit amd_iommu_v2_exit(void) 977static void __exit amd_iommu_v2_exit(void)
977{ 978{
978 struct device_state *dev_state; 979 struct device_state *dev_state;
979 size_t state_table_size;
980 int i; 980 int i;
981 981
982 if (!amd_iommu_v2_supported()) 982 if (!amd_iommu_v2_supported())
@@ -1005,9 +1005,6 @@ static void __exit amd_iommu_v2_exit(void)
1005 1005
1006 destroy_workqueue(iommu_wq); 1006 destroy_workqueue(iommu_wq);
1007 1007
1008 state_table_size = MAX_DEVICES * sizeof(struct device_state *);
1009 free_pages((unsigned long)state_table, get_order(state_table_size));
1010
1011 free_page((unsigned long)empty_page_table); 1008 free_page((unsigned long)empty_page_table);
1012} 1009}
1013 1010