aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/dmar.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2014-03-07 10:08:36 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2014-03-24 10:05:08 -0400
commit832bd858674023b2415c7585db3beba345ef807f (patch)
treef45c9360a2ff71957f2ac3f7a4d83c91e4d7841f /drivers/iommu/dmar.c
parent07cb52ff6aadac0ad68b29be2ef73dba3111c5ec (diff)
iommu/vt-d: Change scope lists to struct device, bus, devfn
It's not only for PCI devices any more, and the scope information for an ACPI device provides the bus and devfn so that has to be stored here too. It is the device pointer itself which needs to be protected with RCU, so the __rcu annotation follows it into the definition of struct dmar_dev_scope, since we're no longer just passing arrays of device pointers around. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r--drivers/iommu/dmar.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 4c6297d1b421..c1e2e0c82e69 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -97,17 +97,17 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt)
97 if (*cnt == 0) 97 if (*cnt == 0)
98 return NULL; 98 return NULL;
99 99
100 return kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL); 100 return kcalloc(*cnt, sizeof(struct dmar_dev_scope), GFP_KERNEL);
101} 101}
102 102
103void dmar_free_dev_scope(struct pci_dev __rcu ***devices, int *cnt) 103void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt)
104{ 104{
105 int i; 105 int i;
106 struct pci_dev *tmp_dev; 106 struct device *tmp_dev;
107 107
108 if (*devices && *cnt) { 108 if (*devices && *cnt) {
109 for_each_active_dev_scope(*devices, *cnt, i, tmp_dev) 109 for_each_active_dev_scope(*devices, *cnt, i, tmp_dev)
110 pci_dev_put(tmp_dev); 110 put_device(tmp_dev);
111 kfree(*devices); 111 kfree(*devices);
112 } 112 }
113 113
@@ -191,10 +191,11 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
191/* Return: > 0 if match found, 0 if no match found, < 0 if error happens */ 191/* Return: > 0 if match found, 0 if no match found, < 0 if error happens */
192int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, 192int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
193 void *start, void*end, u16 segment, 193 void *start, void*end, u16 segment,
194 struct pci_dev __rcu **devices, int devices_cnt) 194 struct dmar_dev_scope *devices,
195 int devices_cnt)
195{ 196{
196 int i, level; 197 int i, level;
197 struct pci_dev *tmp, *dev = info->dev; 198 struct device *tmp, *dev = &info->dev->dev;
198 struct acpi_dmar_device_scope *scope; 199 struct acpi_dmar_device_scope *scope;
199 struct acpi_dmar_pci_path *path; 200 struct acpi_dmar_pci_path *path;
200 201
@@ -213,16 +214,18 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
213 continue; 214 continue;
214 215
215 if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT) ^ 216 if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT) ^
216 (dev->hdr_type == PCI_HEADER_TYPE_NORMAL)) { 217 (info->dev->hdr_type == PCI_HEADER_TYPE_NORMAL)) {
217 pr_warn("Device scope type does not match for %s\n", 218 pr_warn("Device scope type does not match for %s\n",
218 pci_name(dev)); 219 pci_name(info->dev));
219 return -EINVAL; 220 return -EINVAL;
220 } 221 }
221 222
222 for_each_dev_scope(devices, devices_cnt, i, tmp) 223 for_each_dev_scope(devices, devices_cnt, i, tmp)
223 if (tmp == NULL) { 224 if (tmp == NULL) {
224 rcu_assign_pointer(devices[i], 225 devices[i].bus = info->dev->bus->number;
225 pci_dev_get(dev)); 226 devices[i].devfn = info->dev->devfn;
227 rcu_assign_pointer(devices[i].dev,
228 get_device(dev));
226 return 1; 229 return 1;
227 } 230 }
228 BUG_ON(i >= devices_cnt); 231 BUG_ON(i >= devices_cnt);
@@ -232,19 +235,19 @@ int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
232} 235}
233 236
234int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, u16 segment, 237int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, u16 segment,
235 struct pci_dev __rcu **devices, int count) 238 struct dmar_dev_scope *devices, int count)
236{ 239{
237 int index; 240 int index;
238 struct pci_dev *tmp; 241 struct device *tmp;
239 242
240 if (info->seg != segment) 243 if (info->seg != segment)
241 return 0; 244 return 0;
242 245
243 for_each_active_dev_scope(devices, count, index, tmp) 246 for_each_active_dev_scope(devices, count, index, tmp)
244 if (tmp == info->dev) { 247 if (tmp == &info->dev->dev) {
245 rcu_assign_pointer(devices[index], NULL); 248 rcu_assign_pointer(devices[index].dev, NULL);
246 synchronize_rcu(); 249 synchronize_rcu();
247 pci_dev_put(tmp); 250 put_device(tmp);
248 return 1; 251 return 1;
249 } 252 }
250 253
@@ -562,15 +565,15 @@ parse_dmar_table(void)
562 return ret; 565 return ret;
563} 566}
564 567
565static int dmar_pci_device_match(struct pci_dev __rcu *devices[], int cnt, 568static int dmar_pci_device_match(struct dmar_dev_scope devices[],
566 struct pci_dev *dev) 569 int cnt, struct pci_dev *dev)
567{ 570{
568 int index; 571 int index;
569 struct pci_dev *tmp; 572 struct device *tmp;
570 573
571 while (dev) { 574 while (dev) {
572 for_each_active_dev_scope(devices, cnt, index, tmp) 575 for_each_active_dev_scope(devices, cnt, index, tmp)
573 if (dev == tmp) 576 if (dev_is_pci(tmp) && dev == to_pci_dev(tmp))
574 return 1; 577 return 1;
575 578
576 /* Check our parent */ 579 /* Check our parent */