Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-starfive.git] / drivers / iommu / dma-iommu.c
index 5e89804..129c4ba 100644 (file)
@@ -907,17 +907,18 @@ out_free_page:
        return NULL;
 }
 
-void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
+int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
 {
-       struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
+       struct device *dev = msi_desc_to_dev(desc);
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
        struct iommu_dma_cookie *cookie;
        struct iommu_dma_msi_page *msi_page;
-       phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
        unsigned long flags;
 
-       if (!domain || !domain->iova_cookie)
-               return;
+       if (!domain || !domain->iova_cookie) {
+               desc->iommu_cookie = NULL;
+               return 0;
+       }
 
        cookie = domain->iova_cookie;
 
@@ -930,19 +931,26 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
        msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
        spin_unlock_irqrestore(&cookie->msi_lock, flags);
 
-       if (WARN_ON(!msi_page)) {
-               /*
-                * We're called from a void callback, so the best we can do is
-                * 'fail' by filling the message with obviously bogus values.
-                * Since we got this far due to an IOMMU being present, it's
-                * not like the existing address would have worked anyway...
-                */
-               msg->address_hi = ~0U;
-               msg->address_lo = ~0U;
-               msg->data = ~0U;
-       } else {
-               msg->address_hi = upper_32_bits(msi_page->iova);
-               msg->address_lo &= cookie_msi_granule(cookie) - 1;
-               msg->address_lo += lower_32_bits(msi_page->iova);
-       }
+       msi_desc_set_iommu_cookie(desc, msi_page);
+
+       if (!msi_page)
+               return -ENOMEM;
+       return 0;
+}
+
+void iommu_dma_compose_msi_msg(struct msi_desc *desc,
+                              struct msi_msg *msg)
+{
+       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;
+
+       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);
 }