aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2018-03-22 11:22:34 -0400
committerJoerg Roedel <jroedel@suse.de>2018-03-29 04:38:14 -0400
commit779da73273fc4c4c6f41579a95e4fb7880a1720e (patch)
tree522d6bfd4cf79310c320293ba6b13375515926f4
parent39ffe39545cd5cb5b8cee9f0469165cf24dc62c2 (diff)
iommu/amd: Turn dev_data_list into a lock less list
alloc_dev_data() adds new items to dev_data_list and search_dev_data() is searching for items in this list. Both protect the access to the list with a spinlock. There is no need to navigate forth and back within the list and there is also no deleting of a specific item. This qualifies the list to become a lock less list and as part of this, the spinlock can be removed. With this change the ordering of those items within the list is changed: before the change new items were added to the end of the list, now they are added to the front. I don't think it matters but wanted to mention it. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/amd_iommu.c28
-rw-r--r--drivers/iommu/amd_iommu_types.h2
2 files changed, 11 insertions, 19 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 121c54f1c768..d4c2b1a11924 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -83,8 +83,7 @@
83static DEFINE_RWLOCK(amd_iommu_devtable_lock); 83static DEFINE_RWLOCK(amd_iommu_devtable_lock);
84 84
85/* List of all available dev_data structures */ 85/* List of all available dev_data structures */
86static LIST_HEAD(dev_data_list); 86static LLIST_HEAD(dev_data_list);
87static DEFINE_SPINLOCK(dev_data_list_lock);
88 87
89LIST_HEAD(ioapic_map); 88LIST_HEAD(ioapic_map);
90LIST_HEAD(hpet_map); 89LIST_HEAD(hpet_map);
@@ -203,40 +202,33 @@ static struct dma_ops_domain* to_dma_ops_domain(struct protection_domain *domain
203static struct iommu_dev_data *alloc_dev_data(u16 devid) 202static struct iommu_dev_data *alloc_dev_data(u16 devid)
204{ 203{
205 struct iommu_dev_data *dev_data; 204 struct iommu_dev_data *dev_data;
206 unsigned long flags;
207 205
208 dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); 206 dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
209 if (!dev_data) 207 if (!dev_data)
210 return NULL; 208 return NULL;
211 209
212 dev_data->devid = devid; 210 dev_data->devid = devid;
213
214 spin_lock_irqsave(&dev_data_list_lock, flags);
215 list_add_tail(&dev_data->dev_data_list, &dev_data_list);
216 spin_unlock_irqrestore(&dev_data_list_lock, flags);
217
218 ratelimit_default_init(&dev_data->rs); 211 ratelimit_default_init(&dev_data->rs);
219 212
213 llist_add(&dev_data->dev_data_list, &dev_data_list);
220 return dev_data; 214 return dev_data;
221} 215}
222 216
223static struct iommu_dev_data *search_dev_data(u16 devid) 217static struct iommu_dev_data *search_dev_data(u16 devid)
224{ 218{
225 struct iommu_dev_data *dev_data; 219 struct iommu_dev_data *dev_data;
226 unsigned long flags; 220 struct llist_node *node;
221
222 if (llist_empty(&dev_data_list))
223 return NULL;
227 224
228 spin_lock_irqsave(&dev_data_list_lock, flags); 225 node = dev_data_list.first;
229 list_for_each_entry(dev_data, &dev_data_list, dev_data_list) { 226 llist_for_each_entry(dev_data, node, dev_data_list) {
230 if (dev_data->devid == devid) 227 if (dev_data->devid == devid)
231 goto out_unlock; 228 return dev_data;
232 } 229 }
233 230
234 dev_data = NULL; 231 return NULL;
235
236out_unlock:
237 spin_unlock_irqrestore(&dev_data_list_lock, flags);
238
239 return dev_data;
240} 232}
241 233
242static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) 234static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index da886b0095aa..1c9b080276c9 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -627,7 +627,7 @@ struct devid_map {
627 */ 627 */
628struct iommu_dev_data { 628struct iommu_dev_data {
629 struct list_head list; /* For domain->dev_list */ 629 struct list_head list; /* For domain->dev_list */
630 struct list_head dev_data_list; /* For global dev_data_list */ 630 struct llist_node dev_data_list; /* For global dev_data_list */
631 struct protection_domain *domain; /* Domain the device is bound to */ 631 struct protection_domain *domain; /* Domain the device is bound to */
632 u16 devid; /* PCI Device ID */ 632 u16 devid; /* PCI Device ID */
633 u16 alias; /* Alias Device ID */ 633 u16 alias; /* Alias Device ID */