IOMMU Fixes for Linux v4.2-rc0
Four fixes have queued up to fix regressions introduced after v4.1: * Don't fail IOMMU driver initialization when the add_device call-back returns -ENODEV, as that just means that the device is not translated by the IOMMU. This is pretty common on ARM. * Two fixes for the ARM-SMMU driver for a wrong feature check and to remove a redundant NULL check. * A fix for the AMD IOMMU driver to fix a boot panic on systems where the BIOS requests Unity Mappings in the IVRS table. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJVlBZTAAoJECvwRC2XARrj6ngQAI/fjz1cW4WYVDBGPffoHhtB 9BH72XQTyt2OaQPsiECnWkl4bAoJ0TmS6dvcYTf75znqClL1Eez/TqfATEPOSFwI 7N0qkkVc3OffvF3XnxksNNV4tLaojdIFNdxAVrrOOuWDeNKC4Rkvcx+Typ9Y7CxI YR4+qdkPqjYVn13JVMvZDr6SLAnvfHPSIcW1CP3vQzH6w4mWJSmRMLd42Xel1Kb7 hvEDqlT6k6KJxBt3W601eo3sgqZ1AJTFiY4RFh0diHbHQlgg1PcsbWsL5QJMHozi SSHFDCxag9NgHy97OTcGuDptD9F9fI4+t1ANtWULis7+sN5Bx5/xsG/VRJ9fpiMN RNlcCMCufC89EHXdoPuAvOcoPmUHqv1CU9I6+DpOo9FQrGMoXDrdosApNaJZ73E/ qtgzJN0hueeBOvB7Hk+U+mI4BSzAtGguHoO+LzjrZBzoW5L9WWuznmHYriLE0bMm uKnZFBEnXFe8DugQ3ta7PkyzIWsnD0O++NRueN9pSOLvOUpNk6Iddv4hER9QwwPA RQOfsASEo1ResAd9SJGnPX1MQxXxl4OB/9R1Q648lQguAj7WhV1nn21cISgLjESC nEKma+A7dGT6nOTm/wK+wokAgndOGlztMU9wJBK12ozxrhbO+0VP/oTjhhmvcWGb DbpzhyeCpi1qLmsZe0x7 =NzGR -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pul IOMMU fixes from Joerg Roedel: "Four fixes have queued up to fix regressions introduced after v4.1: - Don't fail IOMMU driver initialization when the add_device call-back returns -ENODEV, as that just means that the device is not translated by the IOMMU. This is pretty common on ARM. - Two fixes for the ARM-SMMU driver for a wrong feature check and to remove a redundant NULL check. - A fix for the AMD IOMMU driver to fix a boot panic on systems where the BIOS requests Unity Mappings in the IVRS table" * tag 'iommu-fixes-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/amd: Introduce protection_domain_init() function iommu/arm-smmu: Delete an unnecessary check before the function call "free_io_pgtable_ops" iommu/arm-smmu: Fix broken ATOS check iommu: Ignore -ENODEV errors from add_device call-back
This commit is contained in:
Коммит
44b061f77f
|
@ -117,6 +117,7 @@ struct kmem_cache *amd_iommu_irq_cache;
|
||||||
|
|
||||||
static void update_domain(struct protection_domain *domain);
|
static void update_domain(struct protection_domain *domain);
|
||||||
static int alloc_passthrough_domain(void);
|
static int alloc_passthrough_domain(void);
|
||||||
|
static int protection_domain_init(struct protection_domain *domain);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -1881,12 +1882,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void)
|
||||||
if (!dma_dom)
|
if (!dma_dom)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
spin_lock_init(&dma_dom->domain.lock);
|
if (protection_domain_init(&dma_dom->domain))
|
||||||
|
|
||||||
dma_dom->domain.id = domain_id_alloc();
|
|
||||||
if (dma_dom->domain.id == 0)
|
|
||||||
goto free_dma_dom;
|
goto free_dma_dom;
|
||||||
INIT_LIST_HEAD(&dma_dom->domain.dev_list);
|
|
||||||
dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
|
dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
|
||||||
dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
|
dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
|
||||||
dma_dom->domain.flags = PD_DMA_OPS_MASK;
|
dma_dom->domain.flags = PD_DMA_OPS_MASK;
|
||||||
|
@ -2916,6 +2914,18 @@ static void protection_domain_free(struct protection_domain *domain)
|
||||||
kfree(domain);
|
kfree(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int protection_domain_init(struct protection_domain *domain)
|
||||||
|
{
|
||||||
|
spin_lock_init(&domain->lock);
|
||||||
|
mutex_init(&domain->api_lock);
|
||||||
|
domain->id = domain_id_alloc();
|
||||||
|
if (!domain->id)
|
||||||
|
return -ENOMEM;
|
||||||
|
INIT_LIST_HEAD(&domain->dev_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct protection_domain *protection_domain_alloc(void)
|
static struct protection_domain *protection_domain_alloc(void)
|
||||||
{
|
{
|
||||||
struct protection_domain *domain;
|
struct protection_domain *domain;
|
||||||
|
@ -2924,12 +2934,8 @@ static struct protection_domain *protection_domain_alloc(void)
|
||||||
if (!domain)
|
if (!domain)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
spin_lock_init(&domain->lock);
|
if (protection_domain_init(domain))
|
||||||
mutex_init(&domain->api_lock);
|
|
||||||
domain->id = domain_id_alloc();
|
|
||||||
if (!domain->id)
|
|
||||||
goto out_err;
|
goto out_err;
|
||||||
INIT_LIST_HEAD(&domain->dev_list);
|
|
||||||
|
|
||||||
add_domain_to_list(domain);
|
add_domain_to_list(domain);
|
||||||
|
|
||||||
|
|
|
@ -1389,7 +1389,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
|
||||||
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
|
||||||
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
||||||
|
|
||||||
if (smmu_domain->pgtbl_ops)
|
|
||||||
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
|
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
|
||||||
|
|
||||||
/* Free the CD and ASID, if we allocated them */
|
/* Free the CD and ASID, if we allocated them */
|
||||||
|
|
|
@ -1566,7 +1566,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
|
if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) {
|
||||||
smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
|
smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
|
||||||
dev_notice(smmu->dev, "\taddress translation ops\n");
|
dev_notice(smmu->dev, "\taddress translation ops\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -847,13 +847,24 @@ static int add_iommu_group(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
struct iommu_callback_data *cb = data;
|
struct iommu_callback_data *cb = data;
|
||||||
const struct iommu_ops *ops = cb->ops;
|
const struct iommu_ops *ops = cb->ops;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!ops->add_device)
|
if (!ops->add_device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
WARN_ON(dev->iommu_group);
|
WARN_ON(dev->iommu_group);
|
||||||
|
|
||||||
return ops->add_device(dev);
|
ret = ops->add_device(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We ignore -ENODEV errors for now, as they just mean that the
|
||||||
|
* device is not translated by an IOMMU. We still care about
|
||||||
|
* other errors and fail to initialize when they happen.
|
||||||
|
*/
|
||||||
|
if (ret == -ENODEV)
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_iommu_group(struct device *dev, void *data)
|
static int remove_iommu_group(struct device *dev, void *data)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче