diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-08 20:44:33 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-08 20:44:33 +0300 |
commit | 18f1837632783fec017fd932a812d383e3406af0 (patch) | |
tree | f1d51043891abcccbfd5be0b13fe56ebf114108f /drivers/iommu/amd_iommu.c | |
parent | f4e70c2e5f1406e715f6359ae341e76e5004fb98 (diff) | |
parent | 1f568357117cafb48aafb10413cbd1567dc015b1 (diff) | |
download | linux-18f1837632783fec017fd932a812d383e3406af0.tar.xz |
Merge tag 'iommu-updates-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel:
"Nothing big this time. In particular:
- Debugging code for Tegra-GART
- Improvement in Intel VT-d fault printing to prevent soft-lockups
when on fault storms
- Improvements in AMD IOMMU event reporting
- NUMA aware allocation in io-pgtable code for ARM
- Various other small fixes and cleanups all over the place"
* tag 'iommu-updates-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
iommu/io-pgtable-arm: Make allocations NUMA-aware
iommu/amd: Prevent possible null pointer dereference and infinite loop
iommu/amd: Fix grammar of comments
iommu: Clean up the comments for iommu_group_alloc
iommu/vt-d: Remove unnecessary parentheses
iommu/vt-d: Clean up pasid quirk for pre-production devices
iommu/vt-d: Clean up unused variable in find_or_alloc_domain
iommu/vt-d: Fix iotlb psi missing for mappings
iommu/vt-d: Introduce __mapping_notify_one()
iommu: Remove extra NULL check when call strtobool()
iommu/amd: Update logging information for new event type
iommu/amd: Update the PASID information printed to the system log
iommu/tegra: gart: Fix gart_iommu_unmap()
iommu/tegra: gart: Add debugging facility
iommu/io-pgtable-arm: Use for_each_set_bit to simplify code
iommu/qcom: Simplify getting .drvdata
iommu: Remove depends on HAS_DMA in case of platform dependency
iommu/vt-d: Ratelimit each dmar fault printing
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index d60c7dc62905..1912e9106fbe 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -547,7 +547,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, static void iommu_print_event(struct amd_iommu *iommu, void *__evt) { struct device *dev = iommu->iommu.dev; - int type, devid, domid, flags; + int type, devid, pasid, flags, tag; volatile u32 *event = __evt; int count = 0; u64 address; @@ -555,7 +555,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) retry: type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; - domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; + pasid = PPR_PASID(*(u64 *)&event[0]); flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; address = (u64)(((u64)event[3]) << 32) | event[2]; @@ -570,7 +570,7 @@ retry: } if (type == EVENT_TYPE_IO_FAULT) { - amd_iommu_report_page_fault(devid, domid, address, flags); + amd_iommu_report_page_fault(devid, pasid, address, flags); return; } else { dev_err(dev, "AMD-Vi: Event logged ["); @@ -578,10 +578,9 @@ retry: switch (type) { case EVENT_TYPE_ILL_DEV: - dev_err(dev, "ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " - "address=0x%016llx flags=0x%04x]\n", + dev_err(dev, "ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n", PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), - address, flags); + pasid, address, flags); dump_dte_entry(devid); break; case EVENT_TYPE_DEV_TAB_ERR: @@ -591,34 +590,38 @@ retry: address, flags); break; case EVENT_TYPE_PAGE_TAB_ERR: - dev_err(dev, "PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " - "domain=0x%04x address=0x%016llx flags=0x%04x]\n", + dev_err(dev, "PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x domain=0x%04x address=0x%016llx flags=0x%04x]\n", PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), - domid, address, flags); + pasid, address, flags); break; case EVENT_TYPE_ILL_CMD: dev_err(dev, "ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); dump_command(address); break; case EVENT_TYPE_CMD_HARD_ERR: - dev_err(dev, "COMMAND_HARDWARE_ERROR address=0x%016llx " - "flags=0x%04x]\n", address, flags); + dev_err(dev, "COMMAND_HARDWARE_ERROR address=0x%016llx flags=0x%04x]\n", + address, flags); break; case EVENT_TYPE_IOTLB_INV_TO: - dev_err(dev, "IOTLB_INV_TIMEOUT device=%02x:%02x.%x " - "address=0x%016llx]\n", + dev_err(dev, "IOTLB_INV_TIMEOUT device=%02x:%02x.%x address=0x%016llx]\n", PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), address); break; case EVENT_TYPE_INV_DEV_REQ: - dev_err(dev, "INVALID_DEVICE_REQUEST device=%02x:%02x.%x " - "address=0x%016llx flags=0x%04x]\n", + dev_err(dev, "INVALID_DEVICE_REQUEST device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n", PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), - address, flags); + pasid, address, flags); + break; + case EVENT_TYPE_INV_PPR_REQ: + pasid = ((event[0] >> 16) & 0xFFFF) + | ((event[1] << 6) & 0xF0000); + tag = event[1] & 0x03FF; + dev_err(dev, "INVALID_PPR_REQUEST device=%02x:%02x.%x pasid=0x%05x address=0x%016llx flags=0x%04x]\n", + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + pasid, address, flags); break; default: - dev_err(dev, KERN_ERR "UNKNOWN event[0]=0x%08x event[1]=0x%08x " - "event[2]=0x%08x event[3]=0x%08x\n", + dev_err(dev, "UNKNOWN event[0]=0x%08x event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n", event[0], event[1], event[2], event[3]); } @@ -1914,15 +1917,6 @@ static void do_detach(struct iommu_dev_data *dev_data) struct amd_iommu *iommu; u16 alias; - /* - * First check if the device is still attached. It might already - * be detached from its domain because the generic - * iommu_detach_group code detached it and we try again here in - * our alias handling. - */ - if (!dev_data->domain) - return; - iommu = amd_iommu_rlookup_table[dev_data->devid]; alias = dev_data->alias; @@ -1942,8 +1936,8 @@ static void do_detach(struct iommu_dev_data *dev_data) } /* - * If a device is not yet associated with a domain, this function does - * assigns it visible for the hardware + * If a device is not yet associated with a domain, this function makes the + * device visible in the domain */ static int __attach_device(struct iommu_dev_data *dev_data, struct protection_domain *domain) @@ -2064,8 +2058,8 @@ static bool pci_pri_tlp_required(struct pci_dev *pdev) } /* - * If a device is not yet associated with a domain, this function - * assigns it visible for the hardware + * If a device is not yet associated with a domain, this function makes the + * device visible in the domain */ static int attach_device(struct device *dev, struct protection_domain *domain) @@ -2127,9 +2121,6 @@ static void __detach_device(struct iommu_dev_data *dev_data) */ WARN_ON(!irqs_disabled()); - if (WARN_ON(!dev_data->domain)) - return; - domain = dev_data->domain; spin_lock(&domain->lock); @@ -2151,6 +2142,15 @@ static void detach_device(struct device *dev) dev_data = get_dev_data(dev); domain = dev_data->domain; + /* + * First check if the device is still attached. It might already + * be detached from its domain because the generic + * iommu_detach_group code detached it and we try again here in + * our alias handling. + */ + if (WARN_ON(!dev_data->domain)) + return; + /* lock device table */ spin_lock_irqsave(&amd_iommu_devtable_lock, flags); __detach_device(dev_data); @@ -2796,6 +2796,7 @@ static void cleanup_domain(struct protection_domain *domain) while (!list_empty(&domain->dev_list)) { entry = list_first_entry(&domain->dev_list, struct iommu_dev_data, list); + BUG_ON(!entry->domain); __detach_device(entry); } |