diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 8d2e26f00988..cabbcbb20a02 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1726,7 +1726,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) static DEFINE_MUTEX(msi_prepare_lock); /* see below */ if (!domain || !domain->iova_cookie) { - msi_desc_set_iommu_msi_iova(desc, 0, 0); + desc->iommu_cookie = NULL; return 0; } @@ -1738,12 +1738,11 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) mutex_lock(&msi_prepare_lock); msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); mutex_unlock(&msi_prepare_lock); + + msi_desc_set_iommu_cookie(desc, msi_page); + if (!msi_page) return -ENOMEM; - - msi_desc_set_iommu_msi_iova( - desc, msi_page->iova, - ilog2(cookie_msi_granule(domain->iova_cookie))); return 0; } @@ -1754,15 +1753,18 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) */ void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg) { -#ifdef CONFIG_IRQ_MSI_IOMMU - if (desc->iommu_msi_shift) { - u64 msi_iova = desc->iommu_msi_iova << desc->iommu_msi_shift; + struct device *dev = msi_desc_to_dev(desc); + const struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + const struct iommu_dma_msi_page *msi_page; - msg->address_hi = upper_32_bits(msi_iova); - msg->address_lo = lower_32_bits(msi_iova) | - (msg->address_lo & ((1 << desc->iommu_msi_shift) - 1)); - } -#endif + msi_page = msi_desc_get_iommu_cookie(desc); + + if (!domain || !domain->iova_cookie || WARN_ON(!msi_page)) + return; + + msg->address_hi = upper_32_bits(msi_page->iova); + msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1; + msg->address_lo += lower_32_bits(msi_page->iova); } static int iommu_dma_init(void) diff --git a/include/linux/msi.h b/include/linux/msi.h index 2cf15cf5d060..ddace8c34dcf 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -171,10 +171,6 @@ struct msi_desc_data { * @dev: Pointer to the device which uses this descriptor * @msg: The last set MSI message cached for reuse * @affinity: Optional pointer to a cpu affinity mask for this descriptor - * @iommu_msi_iova: Optional shifted IOVA from the IOMMU to override the msi_addr. - * Only used if iommu_msi_shift != 0 - * @iommu_msi_shift: Indicates how many bits of the original address should be - * preserved when using iommu_msi_iova. * @sysfs_attr: Pointer to sysfs device attribute * * @write_msi_msg: Callback that may be called when the MSI message @@ -193,8 +189,7 @@ struct msi_desc { struct msi_msg msg; struct irq_affinity_desc *affinity; #ifdef CONFIG_IRQ_MSI_IOMMU - u64 iommu_msi_iova : 58; - u64 iommu_msi_shift : 6; + const void *iommu_cookie; #endif #ifdef CONFIG_SYSFS struct device_attribute *sysfs_attrs; @@ -311,15 +306,29 @@ struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, #define msi_desc_to_dev(desc) ((desc)->dev) -static inline void msi_desc_set_iommu_msi_iova(struct msi_desc *desc, u64 msi_iova, - unsigned int msi_shift) -{ #ifdef CONFIG_IRQ_MSI_IOMMU - desc->iommu_msi_iova = msi_iova >> msi_shift; - desc->iommu_msi_shift = msi_shift; -#endif +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) +{ + return desc->iommu_cookie; } +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, + const void *iommu_cookie) +{ + desc->iommu_cookie = iommu_cookie; +} +#else +static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) +{ + return NULL; +} + +static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, + const void *iommu_cookie) +{ +} +#endif + int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, struct msi_desc *init_desc); /**