mirror of https://gitee.com/openkylin/linux.git
IOMMU-Fixes for Linux v4.9-rc4
Two places need fixing: * Four patches from Robin Murphy fix several issues with the recently merged generic DT-bindings support for arm-smmu drivers * A fix for a dead-lock issue in the VT-d driver, which shows up on iommu hotplug -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJYIe6KAAoJECvwRC2XARrjJtgP/0O2b5JBuMGPBdCcFdClGji4 ozxDwfOMUohRfo6p33V7G+bQiNmF5NUhqWPuEXQ64BejFe3GY2+jWS5C0bj2w+Cm 5u8C5K6WJ93q2Bdg8BLhe17H00kjM+vFucMZBvcZlDWZlrDzbSR1tVG84zhlAUR+ ewuBzf8qEAAK1xLuVU6ywLBHK6L/tX4mACgvwktQR8qRrz5bGGIecH9ZAHCzYODb 6PJ3/hchn1e0Ckntg1i+Ggx6A9+aof+U+t0iJeFBN1HpAuN+FhaGNmf8b7v7AQAn 0el/ByVfp51kzGo1/mi/bW1odgNMSqhOn+oA2Na2fHrn9A0/2c8LtYmsGmRacNqi HPLm0iKAZUb7HAKlSJnm4eVjQsFxAcIXe+rEE3RgxJbbKpWPVy2zaEXw6c++ALhi R2xI1L9cLXhV/bOfba05uuSTp604yAFcli4tbo81AziZZ+hpXCPTAYrjtw11LbiC JaFBPksctESm2bOSDXkbSgwIQN+jRnMH7xR/t9L2vCIt0m3IGCFqz5ia4rcmCq1+ quRp6GCd9G2oW8DemI9bggYCZeGzbWbOAQCQfKoRGl50WJ279vUpVhpUUo8OBcPg xE+GqGNAEcWchNDODH5nVrfuCK3TV0NWW+N3tOh0IC2QT85JMa+9nc287vq4ZwqQ bhionSy/gs2ht9NPa9XO =N8iu -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull IOMMU fixes from Joerg Roedel: - Four patches from Robin Murphy fix several issues with the recently merged generic DT-bindings support for arm-smmu drivers - A fix for a dead-lock issue in the VT-d driver, which shows up on iommu hotplug * tag 'iommu-fixes-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/vt-d: Fix dead-locks in disable_dmar_iommu() path iommu/arm-smmu: Fix out-of-bounds dereference iommu/arm-smmu: Check that iommu_fwspecs are ours iommu/arm-smmu: Don't inadvertently reject multiple SMMUv3s iommu/arm-smmu: Work around ARM DMA configuration
This commit is contained in:
commit
e3a00f68e4
|
@ -2636,17 +2636,26 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|||
/* And we're up. Go go go! */
|
||||
of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
|
||||
#ifdef CONFIG_PCI
|
||||
pci_request_acs();
|
||||
ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (pci_bus_type.iommu_ops != &arm_smmu_ops) {
|
||||
pci_request_acs();
|
||||
ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_AMBA
|
||||
ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (amba_bustype.iommu_ops != &arm_smmu_ops) {
|
||||
ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
|
||||
if (platform_bus_type.iommu_ops != &arm_smmu_ops) {
|
||||
ret = bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arm_smmu_device_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -324,8 +324,10 @@ struct arm_smmu_master_cfg {
|
|||
#define INVALID_SMENDX -1
|
||||
#define __fwspec_cfg(fw) ((struct arm_smmu_master_cfg *)fw->iommu_priv)
|
||||
#define fwspec_smmu(fw) (__fwspec_cfg(fw)->smmu)
|
||||
#define fwspec_smendx(fw, i) \
|
||||
(i >= fw->num_ids ? INVALID_SMENDX : __fwspec_cfg(fw)->smendx[i])
|
||||
#define for_each_cfg_sme(fw, i, idx) \
|
||||
for (i = 0; idx = __fwspec_cfg(fw)->smendx[i], i < fw->num_ids; ++i)
|
||||
for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i)
|
||||
|
||||
struct arm_smmu_device {
|
||||
struct device *dev;
|
||||
|
@ -1228,6 +1230,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: The arch/arm DMA API code tries to attach devices to its own
|
||||
* domains between of_xlate() and add_device() - we have no way to cope
|
||||
* with that, so until ARM gets converted to rely on groups and default
|
||||
* domains, just say no (but more politely than by dereferencing NULL).
|
||||
* This should be at least a WARN_ON once that's sorted.
|
||||
*/
|
||||
if (!fwspec->iommu_priv)
|
||||
return -ENODEV;
|
||||
|
||||
smmu = fwspec_smmu(fwspec);
|
||||
/* Ensure that the domain is finalised */
|
||||
ret = arm_smmu_init_domain_context(domain, smmu);
|
||||
|
@ -1390,7 +1402,7 @@ static int arm_smmu_add_device(struct device *dev)
|
|||
fwspec = dev->iommu_fwspec;
|
||||
if (ret)
|
||||
goto out_free;
|
||||
} else if (fwspec) {
|
||||
} else if (fwspec && fwspec->ops == &arm_smmu_ops) {
|
||||
smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
|
||||
} else {
|
||||
return -ENODEV;
|
||||
|
|
|
@ -1711,6 +1711,7 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
|
|||
if (!iommu->domains || !iommu->domain_ids)
|
||||
return;
|
||||
|
||||
again:
|
||||
spin_lock_irqsave(&device_domain_lock, flags);
|
||||
list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
|
||||
struct dmar_domain *domain;
|
||||
|
@ -1723,10 +1724,19 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
|
|||
|
||||
domain = info->domain;
|
||||
|
||||
dmar_remove_one_dev_info(domain, info->dev);
|
||||
__dmar_remove_one_dev_info(info);
|
||||
|
||||
if (!domain_type_is_vm_or_si(domain))
|
||||
if (!domain_type_is_vm_or_si(domain)) {
|
||||
/*
|
||||
* The domain_exit() function can't be called under
|
||||
* device_domain_lock, as it takes this lock itself.
|
||||
* So release the lock here and re-run the loop
|
||||
* afterwards.
|
||||
*/
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
domain_exit(domain);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
|
||||
|
|
Loading…
Reference in New Issue