aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/dmar.c89
-rw-r--r--drivers/pci/intel-iommu.c10
-rw-r--r--drivers/pci/intel-iommu.h2
3 files changed, 79 insertions, 22 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 1a59423a8eda..158bc5bfcf75 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -174,19 +174,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
174 struct acpi_dmar_hardware_unit *drhd; 174 struct acpi_dmar_hardware_unit *drhd;
175 struct dmar_drhd_unit *dmaru; 175 struct dmar_drhd_unit *dmaru;
176 int ret = 0; 176 int ret = 0;
177 static int include_all;
178 177
179 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); 178 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
180 if (!dmaru) 179 if (!dmaru)
181 return -ENOMEM; 180 return -ENOMEM;
182 181
182 dmaru->hdr = header;
183 drhd = (struct acpi_dmar_hardware_unit *)header; 183 drhd = (struct acpi_dmar_hardware_unit *)header;
184 dmaru->reg_base_addr = drhd->address; 184 dmaru->reg_base_addr = drhd->address;
185 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ 185 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
186 186
187 ret = alloc_iommu(dmaru);
188 if (ret) {
189 kfree(dmaru);
190 return ret;
191 }
192 dmar_register_drhd_unit(dmaru);
193 return 0;
194}
195
196static int __init
197dmar_parse_dev(struct dmar_drhd_unit *dmaru)
198{
199 struct acpi_dmar_hardware_unit *drhd;
200 static int include_all;
201 int ret;
202
203 drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
204
187 if (!dmaru->include_all) 205 if (!dmaru->include_all)
188 ret = dmar_parse_dev_scope((void *)(drhd + 1), 206 ret = dmar_parse_dev_scope((void *)(drhd + 1),
189 ((void *)drhd) + header->length, 207 ((void *)drhd) + drhd->header.length,
190 &dmaru->devices_cnt, &dmaru->devices, 208 &dmaru->devices_cnt, &dmaru->devices,
191 drhd->segment); 209 drhd->segment);
192 else { 210 else {
@@ -199,10 +217,10 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
199 include_all = 1; 217 include_all = 1;
200 } 218 }
201 219
202 if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) 220 if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
221 list_del(&dmaru->list);
203 kfree(dmaru); 222 kfree(dmaru);
204 else 223 }
205 dmar_register_drhd_unit(dmaru);
206 return ret; 224 return ret;
207} 225}
208 226
@@ -211,23 +229,35 @@ dmar_parse_one_rmrr(struct acpi_dmar_header *header)
211{ 229{
212 struct acpi_dmar_reserved_memory *rmrr; 230 struct acpi_dmar_reserved_memory *rmrr;
213 struct dmar_rmrr_unit *rmrru; 231 struct dmar_rmrr_unit *rmrru;
214 int ret = 0;
215 232
216 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); 233 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
217 if (!rmrru) 234 if (!rmrru)
218 return -ENOMEM; 235 return -ENOMEM;
219 236
237 rmrru->hdr = header;
220 rmrr = (struct acpi_dmar_reserved_memory *)header; 238 rmrr = (struct acpi_dmar_reserved_memory *)header;
221 rmrru->base_address = rmrr->base_address; 239 rmrru->base_address = rmrr->base_address;
222 rmrru->end_address = rmrr->end_address; 240 rmrru->end_address = rmrr->end_address;
241
242 dmar_register_rmrr_unit(rmrru);
243 return 0;
244}
245
246static int __init
247rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
248{
249 struct acpi_dmar_reserved_memory *rmrr;
250 int ret;
251
252 rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
223 ret = dmar_parse_dev_scope((void *)(rmrr + 1), 253 ret = dmar_parse_dev_scope((void *)(rmrr + 1),
224 ((void *)rmrr) + header->length, 254 ((void *)rmrr) + rmrr->header.length,
225 &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); 255 &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
226 256
227 if (ret || (rmrru->devices_cnt == 0)) 257 if (ret || (rmrru->devices_cnt == 0)) {
258 list_del(&rmrru->list);
228 kfree(rmrru); 259 kfree(rmrru);
229 else 260 }
230 dmar_register_rmrr_unit(rmrru);
231 return ret; 261 return ret;
232} 262}
233 263
@@ -333,15 +363,42 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
333 return NULL; 363 return NULL;
334} 364}
335 365
366int __init dmar_dev_scope_init(void)
367{
368 struct dmar_drhd_unit *drhd;
369 struct dmar_rmrr_unit *rmrr;
370 int ret = -ENODEV;
371
372 for_each_drhd_unit(drhd) {
373 ret = dmar_parse_dev(drhd);
374 if (ret)
375 return ret;
376 }
377
378 for_each_rmrr_units(rmrr) {
379 ret = rmrr_parse_dev(rmrr);
380 if (ret)
381 return ret;
382 }
383
384 return ret;
385}
386
336 387
337int __init dmar_table_init(void) 388int __init dmar_table_init(void)
338{ 389{
339 390 static int dmar_table_initialized;
340 int ret; 391 int ret;
341 392
393 if (dmar_table_initialized)
394 return 0;
395
396 dmar_table_initialized = 1;
397
342 ret = parse_dmar_table(); 398 ret = parse_dmar_table();
343 if (ret) { 399 if (ret) {
344 printk(KERN_INFO PREFIX "parse DMAR table failure.\n"); 400 if (ret != -ENODEV)
401 printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
345 return ret; 402 return ret;
346 } 403 }
347 404
@@ -377,7 +434,7 @@ int __init early_dmar_detect(void)
377 return (ACPI_SUCCESS(status) ? 1 : 0); 434 return (ACPI_SUCCESS(status) ? 1 : 0);
378} 435}
379 436
380struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) 437int alloc_iommu(struct dmar_drhd_unit *drhd)
381{ 438{
382 struct intel_iommu *iommu; 439 struct intel_iommu *iommu;
383 int map_size; 440 int map_size;
@@ -386,7 +443,7 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
386 443
387 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 444 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
388 if (!iommu) 445 if (!iommu)
389 return NULL; 446 return -ENOMEM;
390 447
391 iommu->seq_id = iommu_allocated++; 448 iommu->seq_id = iommu_allocated++;
392 449
@@ -419,10 +476,10 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
419 spin_lock_init(&iommu->register_lock); 476 spin_lock_init(&iommu->register_lock);
420 477
421 drhd->iommu = iommu; 478 drhd->iommu = iommu;
422 return iommu; 479 return 0;
423error: 480error:
424 kfree(iommu); 481 kfree(iommu);
425 return NULL; 482 return -1;
426} 483}
427 484
428void free_iommu(struct intel_iommu *iommu) 485void free_iommu(struct intel_iommu *iommu)
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 4d59a6a1f4dd..218a1f357b4d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1665,11 +1665,8 @@ int __init init_dmars(void)
1665 for_each_drhd_unit(drhd) { 1665 for_each_drhd_unit(drhd) {
1666 if (drhd->ignored) 1666 if (drhd->ignored)
1667 continue; 1667 continue;
1668 iommu = alloc_iommu(drhd); 1668
1669 if (!iommu) { 1669 iommu = drhd->iommu;
1670 ret = -ENOMEM;
1671 goto error;
1672 }
1673 1670
1674 ret = iommu_init_domains(iommu); 1671 ret = iommu_init_domains(iommu);
1675 if (ret) 1672 if (ret)
@@ -2324,6 +2321,9 @@ int __init intel_iommu_init(void)
2324 if (dmar_table_init()) 2321 if (dmar_table_init())
2325 return -ENODEV; 2322 return -ENODEV;
2326 2323
2324 if (dmar_dev_scope_init())
2325 return -ENODEV;
2326
2327 iommu_init_mempool(); 2327 iommu_init_mempool();
2328 dmar_init_reserved_ranges(); 2328 dmar_init_reserved_ranges();
2329 2329
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
index 75c63f65b3f5..371e3b9caf32 100644
--- a/drivers/pci/intel-iommu.h
+++ b/drivers/pci/intel-iommu.h
@@ -199,7 +199,7 @@ struct intel_iommu {
199 199
200extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); 200extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
201 201
202extern struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd); 202extern int alloc_iommu(struct dmar_drhd_unit *drhd);
203extern void free_iommu(struct intel_iommu *iommu); 203extern void free_iommu(struct intel_iommu *iommu);
204 204
205#endif 205#endif