diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 5ed5117b6087..3425d9b41a62 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1679,7 +1679,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; } @@ -1691,12 +1691,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; } @@ -1707,15 +1706,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 1bf8d126f792..e5dfb9cf3aa1 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -129,10 +129,6 @@ struct pci_msi_desc { * @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 @@ -150,8 +146,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; @@ -219,15 +214,29 @@ struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter); #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 + #ifdef CONFIG_PCI_MSI struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc); void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg);