summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/Kconfig1
-rw-r--r--drivers/iommu/dma-iommu.c46
-rw-r--r--include/linux/dma-iommu.h25
3 files changed, 63 insertions, 9 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6f07f3b21816..eb1c8cd243f9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -94,6 +94,7 @@ config IOMMU_DMA
94 bool 94 bool
95 select IOMMU_API 95 select IOMMU_API
96 select IOMMU_IOVA 96 select IOMMU_IOVA
97 select IRQ_MSI_IOMMU
97 select NEED_SG_DMA_LENGTH 98 select NEED_SG_DMA_LENGTH
98 99
99config FSL_PAMU 100config FSL_PAMU
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 77aabe637a60..f847904098f7 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -888,17 +888,18 @@ out_free_page:
888 return NULL; 888 return NULL;
889} 889}
890 890
891void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) 891int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
892{ 892{
893 struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq)); 893 struct device *dev = msi_desc_to_dev(desc);
894 struct iommu_domain *domain = iommu_get_domain_for_dev(dev); 894 struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
895 struct iommu_dma_cookie *cookie; 895 struct iommu_dma_cookie *cookie;
896 struct iommu_dma_msi_page *msi_page; 896 struct iommu_dma_msi_page *msi_page;
897 phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
898 unsigned long flags; 897 unsigned long flags;
899 898
900 if (!domain || !domain->iova_cookie) 899 if (!domain || !domain->iova_cookie) {
901 return; 900 desc->iommu_cookie = NULL;
901 return 0;
902 }
902 903
903 cookie = domain->iova_cookie; 904 cookie = domain->iova_cookie;
904 905
@@ -911,7 +912,36 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
911 msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); 912 msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
912 spin_unlock_irqrestore(&cookie->msi_lock, flags); 913 spin_unlock_irqrestore(&cookie->msi_lock, flags);
913 914
914 if (WARN_ON(!msi_page)) { 915 msi_desc_set_iommu_cookie(desc, msi_page);
916
917 if (!msi_page)
918 return -ENOMEM;
919 return 0;
920}
921
922void iommu_dma_compose_msi_msg(struct msi_desc *desc,
923 struct msi_msg *msg)
924{
925 struct device *dev = msi_desc_to_dev(desc);
926 const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
927 const struct iommu_dma_msi_page *msi_page;
928
929 msi_page = msi_desc_get_iommu_cookie(desc);
930
931 if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
932 return;
933
934 msg->address_hi = upper_32_bits(msi_page->iova);
935 msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
936 msg->address_lo += lower_32_bits(msi_page->iova);
937}
938
939void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
940{
941 struct msi_desc *desc = irq_get_msi_desc(irq);
942 phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
943
944 if (WARN_ON(iommu_dma_prepare_msi(desc, msi_addr))) {
915 /* 945 /*
916 * We're called from a void callback, so the best we can do is 946 * We're called from a void callback, so the best we can do is
917 * 'fail' by filling the message with obviously bogus values. 947 * 'fail' by filling the message with obviously bogus values.
@@ -922,8 +952,6 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
922 msg->address_lo = ~0U; 952 msg->address_lo = ~0U;
923 msg->data = ~0U; 953 msg->data = ~0U;
924 } else { 954 } else {
925 msg->address_hi = upper_32_bits(msi_page->iova); 955 iommu_dma_compose_msi_msg(desc, msg);
926 msg->address_lo &= cookie_msi_granule(cookie) - 1;
927 msg->address_lo += lower_32_bits(msi_page->iova);
928 } 956 }
929} 957}
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index e760dc5d1fa8..0b781a98ee73 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -71,12 +71,26 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
71 size_t size, enum dma_data_direction dir, unsigned long attrs); 71 size_t size, enum dma_data_direction dir, unsigned long attrs);
72 72
73/* The DMA API isn't _quite_ the whole story, though... */ 73/* The DMA API isn't _quite_ the whole story, though... */
74/*
75 * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU device
76 *
77 * The MSI page will be stored in @desc.
78 *
79 * Return: 0 on success otherwise an error describing the failure.
80 */
81int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
82
83/* Update the MSI message if required. */
84void iommu_dma_compose_msi_msg(struct msi_desc *desc,
85 struct msi_msg *msg);
86
74void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg); 87void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
75void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); 88void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
76 89
77#else 90#else
78 91
79struct iommu_domain; 92struct iommu_domain;
93struct msi_desc;
80struct msi_msg; 94struct msi_msg;
81struct device; 95struct device;
82 96
@@ -99,6 +113,17 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
99{ 113{
100} 114}
101 115
116static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
117 phys_addr_t msi_addr)
118{
119 return 0;
120}
121
122static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
123 struct msi_msg *msg)
124{
125}
126
102static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) 127static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
103{ 128{
104} 129}