Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.infradead.org/intel-iommu

Pull IOMMU fixes from David Woodhouse:
"Two minor fixes.

The first fixes the assignment of SR-IOV virtual functions to the
correct IOMMU unit, and the second fixes the excessively large (and
physically contiguous) PASID tables used with SVM"

* git://git.infradead.org/intel-iommu:
iommu/vt-d: Fix PASID table allocation
iommu/vt-d: Fix IOMMU lookup for SR-IOV Virtual Functions

+33 -11
+3 -1
drivers/iommu/dmar.c
··· 338 338 struct pci_dev *pdev = to_pci_dev(data); 339 339 struct dmar_pci_notify_info *info; 340 340 341 - /* Only care about add/remove events for physical functions */ 341 + /* Only care about add/remove events for physical functions. 342 + * For VFs we actually do the lookup based on the corresponding 343 + * PF in device_to_iommu() anyway. */ 342 344 if (pdev->is_virtfn) 343 345 return NOTIFY_DONE; 344 346 if (action != BUS_NOTIFY_ADD_DEVICE &&
+13
drivers/iommu/intel-iommu.c
··· 892 892 return NULL; 893 893 894 894 if (dev_is_pci(dev)) { 895 + struct pci_dev *pf_pdev; 896 + 895 897 pdev = to_pci_dev(dev); 898 + /* VFs aren't listed in scope tables; we need to look up 899 + * the PF instead to find the IOMMU. */ 900 + pf_pdev = pci_physfn(pdev); 901 + dev = &pf_pdev->dev; 896 902 segment = pci_domain_nr(pdev->bus); 897 903 } else if (has_acpi_companion(dev)) 898 904 dev = &ACPI_COMPANION(dev)->dev; ··· 911 905 for_each_active_dev_scope(drhd->devices, 912 906 drhd->devices_cnt, i, tmp) { 913 907 if (tmp == dev) { 908 + /* For a VF use its original BDF# not that of the PF 909 + * which we used for the IOMMU lookup. Strictly speaking 910 + * we could do this for all PCI devices; we only need to 911 + * get the BDF# from the scope table for ACPI matches. */ 912 + if (pdev->is_virtfn) 913 + goto got_pdev; 914 + 914 915 *bus = drhd->devices[i].bus; 915 916 *devfn = drhd->devices[i].devfn; 916 917 goto out;
+16 -10
drivers/iommu/intel-svm.c
··· 39 39 struct page *pages; 40 40 int order; 41 41 42 - order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; 43 - if (order < 0) 44 - order = 0; 42 + /* Start at 2 because it's defined as 2^(1+PSS) */ 43 + iommu->pasid_max = 2 << ecap_pss(iommu->ecap); 45 44 45 + /* Eventually I'm promised we will get a multi-level PASID table 46 + * and it won't have to be physically contiguous. Until then, 47 + * limit the size because 8MiB contiguous allocations can be hard 48 + * to come by. The limit of 0x20000, which is 1MiB for each of 49 + * the PASID and PASID-state tables, is somewhat arbitrary. */ 50 + if (iommu->pasid_max > 0x20000) 51 + iommu->pasid_max = 0x20000; 52 + 53 + order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max); 46 54 pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); 47 55 if (!pages) { 48 56 pr_warn("IOMMU: %s: Failed to allocate PASID table\n", ··· 61 53 pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order); 62 54 63 55 if (ecap_dis(iommu->ecap)) { 56 + /* Just making it explicit... */ 57 + BUILD_BUG_ON(sizeof(struct pasid_entry) != sizeof(struct pasid_state_entry)); 64 58 pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); 65 59 if (pages) 66 60 iommu->pasid_state_table = page_address(pages); ··· 78 68 79 69 int intel_svm_free_pasid_tables(struct intel_iommu *iommu) 80 70 { 81 - int order; 82 - 83 - order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; 84 - if (order < 0) 85 - order = 0; 71 + int order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max); 86 72 87 73 if (iommu->pasid_table) { 88 74 free_pages((unsigned long)iommu->pasid_table, order); ··· 377 371 } 378 372 svm->iommu = iommu; 379 373 380 - if (pasid_max > 2 << ecap_pss(iommu->ecap)) 381 - pasid_max = 2 << ecap_pss(iommu->ecap); 374 + if (pasid_max > iommu->pasid_max) 375 + pasid_max = iommu->pasid_max; 382 376 383 377 /* Do not use PASID 0 in caching mode (virtualised IOMMU) */ 384 378 ret = idr_alloc(&iommu->pasid_idr, svm,
+1
include/linux/intel-iommu.h
··· 429 429 struct page_req_dsc *prq; 430 430 unsigned char prq_name[16]; /* Name for PRQ interrupt */ 431 431 struct idr pasid_idr; 432 + u32 pasid_max; 432 433 #endif 433 434 struct q_inval *qi; /* Queued invalidation info */ 434 435 u32 *iommu_state; /* Store iommu states between suspend and resume.*/