Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/kernel/dma/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 2 kB image not shown  

Quelle  ops_helpers.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Helpers for DMA ops implementations.  These generally rely on the fact that
 * the allocated memory contains normal pages in the direct kernel mapping.
 */

#include <linux/dma-map-ops.h>
#include <linux/iommu-dma.h>

static struct page *dma_common_vaddr_to_page(void *cpu_addr)
{
 if (is_vmalloc_addr(cpu_addr))
  return vmalloc_to_page(cpu_addr);
 return virt_to_page(cpu_addr);
}

/*
 * Create scatter-list for the already allocated DMA buffer.
 */

int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
   void *cpu_addr, dma_addr_t dma_addr, size_t size,
   unsigned long attrs)
{
 struct page *page = dma_common_vaddr_to_page(cpu_addr);
 int ret;

 ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
 if (!ret)
  sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
 return ret;
}

/*
 * Create userspace mapping for the DMA-coherent memory.
 */

int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
  void *cpu_addr, dma_addr_t dma_addr, size_t size,
  unsigned long attrs)
{
#ifdef CONFIG_MMU
 unsigned long user_count = vma_pages(vma);
 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 unsigned long off = vma->vm_pgoff;
 struct page *page = dma_common_vaddr_to_page(cpu_addr);
 int ret = -ENXIO;

 vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);

 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
  return ret;

 if (off >= count || user_count > count - off)
  return -ENXIO;

 return remap_pfn_range(vma, vma->vm_start,
   page_to_pfn(page) + vma->vm_pgoff,
   user_count << PAGE_SHIFT, vma->vm_page_prot);
#else
 return -ENXIO;
#endif /* CONFIG_MMU */
}

struct page *dma_common_alloc_pages(struct device *dev, size_t size,
  dma_addr_t *dma_handle, enum dma_data_direction dir, gfp_t gfp)
{
 const struct dma_map_ops *ops = get_dma_ops(dev);
 struct page *page;

 page = dma_alloc_contiguous(dev, size, gfp);
 if (!page)
  page = alloc_pages_node(dev_to_node(dev), gfp, get_order(size));
 if (!page)
  return NULL;

 if (use_dma_iommu(dev))
  *dma_handle = iommu_dma_map_page(dev, page, 0, size, dir,
       DMA_ATTR_SKIP_CPU_SYNC);
 else
  *dma_handle = ops->map_page(dev, page, 0, size, dir,
         DMA_ATTR_SKIP_CPU_SYNC);
 if (*dma_handle == DMA_MAPPING_ERROR) {
  dma_free_contiguous(dev, page, size);
  return NULL;
 }

 memset(page_address(page), 0, size);
 return page;
}

void dma_common_free_pages(struct device *dev, size_t size, struct page *page,
  dma_addr_t dma_handle, enum dma_data_direction dir)
{
 const struct dma_map_ops *ops = get_dma_ops(dev);

 if (use_dma_iommu(dev))
  iommu_dma_unmap_page(dev, dma_handle, size, dir,
         DMA_ATTR_SKIP_CPU_SYNC);
 else if (ops->unmap_page)
  ops->unmap_page(dev, dma_handle, size, dir,
    DMA_ATTR_SKIP_CPU_SYNC);
 dma_free_contiguous(dev, page, size);
}

Messung V0.5
C=95 H=100 G=97

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.