diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2018-03-22 11:22:34 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2018-03-29 04:38:14 -0400 |
commit | 779da73273fc4c4c6f41579a95e4fb7880a1720e (patch) | |
tree | 522d6bfd4cf79310c320293ba6b13375515926f4 | |
parent | 39ffe39545cd5cb5b8cee9f0469165cf24dc62c2 (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.c | 28 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 2 |
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 @@ | |||
83 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); | 83 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); |
84 | 84 | ||
85 | /* List of all available dev_data structures */ | 85 | /* List of all available dev_data structures */ |
86 | static LIST_HEAD(dev_data_list); | 86 | static LLIST_HEAD(dev_data_list); |
87 | static DEFINE_SPINLOCK(dev_data_list_lock); | ||
88 | 87 | ||
89 | LIST_HEAD(ioapic_map); | 88 | LIST_HEAD(ioapic_map); |
90 | LIST_HEAD(hpet_map); | 89 | LIST_HEAD(hpet_map); |
@@ -203,40 +202,33 @@ static struct dma_ops_domain* to_dma_ops_domain(struct protection_domain *domain | |||
203 | static struct iommu_dev_data *alloc_dev_data(u16 devid) | 202 | static 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 | ||
223 | static struct iommu_dev_data *search_dev_data(u16 devid) | 217 | static 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 | |||
236 | out_unlock: | ||
237 | spin_unlock_irqrestore(&dev_data_list_lock, flags); | ||
238 | |||
239 | return dev_data; | ||
240 | } | 232 | } |
241 | 233 | ||
242 | static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) | 234 | static 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 | */ |
628 | struct iommu_dev_data { | 628 | struct 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 */ |