aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/dma/mapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/dma/mapping.c')
-rw-r--r--kernel/dma/mapping.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 1f628e7ac709..b0038ca3aa92 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -116,11 +116,16 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
116 int ret; 116 int ret;
117 117
118 if (!dev_is_dma_coherent(dev)) { 118 if (!dev_is_dma_coherent(dev)) {
119 unsigned long pfn;
120
119 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN)) 121 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
120 return -ENXIO; 122 return -ENXIO;
121 123
122 page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr, 124 /* If the PFN is not valid, we do not have a struct page */
123 dma_addr)); 125 pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
126 if (!pfn_valid(pfn))
127 return -ENXIO;
128 page = pfn_to_page(pfn);
124 } else { 129 } else {
125 page = virt_to_page(cpu_addr); 130 page = virt_to_page(cpu_addr);
126 } 131 }
@@ -145,6 +150,23 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
145} 150}
146EXPORT_SYMBOL(dma_get_sgtable_attrs); 151EXPORT_SYMBOL(dma_get_sgtable_attrs);
147 152
153#ifdef CONFIG_MMU
154/*
155 * Return the page attributes used for mapping dma_alloc_* memory, either in
156 * kernel space if remapping is needed, or to userspace through dma_mmap_*.
157 */
158pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs)
159{
160 if (dev_is_dma_coherent(dev) ||
161 (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) &&
162 (attrs & DMA_ATTR_NON_CONSISTENT)))
163 return prot;
164 if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_MMAP_PGPROT))
165 return arch_dma_mmap_pgprot(dev, prot, attrs);
166 return pgprot_noncached(prot);
167}
168#endif /* CONFIG_MMU */
169
148/* 170/*
149 * Create userspace mapping for the DMA-coherent memory. 171 * Create userspace mapping for the DMA-coherent memory.
150 */ 172 */
@@ -159,7 +181,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
159 unsigned long pfn; 181 unsigned long pfn;
160 int ret = -ENXIO; 182 int ret = -ENXIO;
161 183
162 vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs); 184 vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
163 185
164 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) 186 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
165 return ret; 187 return ret;
@@ -170,7 +192,11 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
170 if (!dev_is_dma_coherent(dev)) { 192 if (!dev_is_dma_coherent(dev)) {
171 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN)) 193 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
172 return -ENXIO; 194 return -ENXIO;
195
196 /* If the PFN is not valid, we do not have a struct page */
173 pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr); 197 pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
198 if (!pfn_valid(pfn))
199 return -ENXIO;
174 } else { 200 } else {
175 pfn = page_to_pfn(virt_to_page(cpu_addr)); 201 pfn = page_to_pfn(virt_to_page(cpu_addr));
176 } 202 }