Remove DMA .map_page and .unmap_page callbacks
Subsystems (10)
cover Remove DMA .map_page and .unmap_page callbacks
Hi,
This series continues following two series:
1. "dma-mapping: migrate to physical address-based API"
https://lore.kernel.org/all/[email protected]
2. "Preparation to .map_page and .unmap_page removal" Preparation to .map_page and .unmap_page removal
In this series, the DMA .map_page/.unmap_page callbacks are converted to newly introduced .map_phys/.unmap_phys interfaces. This conversion allows us to reduce or eliminate (for certain ARCHs) use of struct pages in DMA path.
Thanks
Leon Romanovsky (9):
alpha: Convert mapping routine to rely on physical address MIPS/jazzdma: Provide physical address directly
parisc: Convert DMA map_page to map_phys interface
powerpc: Convert to physical address DMA mapping
sparc64: Use physical address DMA mapping
x86: Use physical address for DMA mapping
vdpa: Convert to physical address DMA mapping
xen: swiotlb: Convert mapping routine to rely on physical address
dma-mapping: remove unused map_page callback
arch/alpha/kernel/pci_iommu.c | 47 ++++++++++-------------- arch/mips/jazz/jazzdma.c | 20 ++++++---- arch/powerpc/include/asm/iommu.h | 8 ++-- arch/powerpc/kernel/dma-iommu.c | 22 +++++------ arch/powerpc/kernel/iommu.c | 14 +++---- arch/powerpc/platforms/ps3/system-bus.c | 33 ++++++++++------- arch/powerpc/platforms/pseries/ibmebus.c | 15 ++++---- arch/powerpc/platforms/pseries/vio.c | 21 ++++++----- arch/sparc/kernel/iommu.c | 16 ++++---- arch/sparc/kernel/pci_sun4v.c | 16 ++++---- arch/sparc/mm/io-unit.c | 13 +++---- arch/sparc/mm/iommu.c | 46 ++++++++++++----------- arch/x86/kernel/amd_gart_64.c | 19 +++++----- drivers/parisc/ccio-dma.c | 25 +++++++------ drivers/parisc/sba_iommu.c | 23 ++++++------ drivers/vdpa/vdpa_user/iova_domain.c | 11 +++--- drivers/vdpa/vdpa_user/iova_domain.h | 8 ++-- drivers/vdpa/vdpa_user/vduse_dev.c | 18 +++++---- drivers/xen/grant-dma-ops.c | 20 ++++++---- include/linux/dma-map-ops.h | 7 ---- kernel/dma/mapping.c | 12 ------ kernel/dma/ops_helpers.c | 8 +--- 22 files changed, 208 insertions(+), 214 deletions(-)
Signature · 1 line
2.51.0
PATCH 1/9 alpha: Convert mapping routine to rely on physical address
From: Leon Romanovsky <[email protected]>
Alpha doesn't need struct *page and can perform mapping based on physical addresses. So convert it to implement new .map_phys callback.
As part of this change, remove useless BUG_ON() as DMA mapping layer ensures that right direction is provided.
--- arch/alpha/kernel/pci_iommu.c | 47 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 27 deletions(-)
arch/alpha/kernel/pci_iommu.c +20 -27
@@ -224,28 +224,25 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)until either pci_unmap_single or pci_dma_sync_single is performed. */ static dma_addr_t -pci_map_single_1 (struct pci_dev *pdev,void *cpu_addr,size_t size, +pci_map_single_1 (struct pci_dev *pdev,phys_addr_t paddr,size_t size,int dac_allowed) {struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;dma_addr_t max_dma = pdev ? pdev->dma_mask :ISA_DMA_MASK ;struct pci_iommu_arena *arena;long npages, dma_ofs, i; -unsigned long paddr;dma_addr_t ret;unsigned int align =0 ;struct device *dev = pdev ? &pdev->dev :NULL ; - paddr =__pa (cpu_addr); -#if !DEBUG_NODIRECT /* First check to see if we can use the direct map window. */ if (paddr + size + __direct_map_base -1 <= max_dma && paddr + size <= __direct_map_size) { ret = paddr + __direct_map_base; -DBGA2 ("pci_map_single: [%p,%zx] -> direct %llx from %ps\n" , - cpu_addr, size, ret,__builtin_return_address (0 )); +DBGA2 ("pci_map_single: [%pa,%zx] -> direct %llx from %ps\n" , + &paddr, size, ret,__builtin_return_address (0 ));return ret; }
@@ -255,8 +252,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,if (dac_allowed) { ret = paddr + alpha_mv.pci_dac_offset; -DBGA2 ("pci_map_single: [%p,%zx] -> DAC %llx from %ps\n" , - cpu_addr, size, ret,__builtin_return_address (0 )); +DBGA2 ("pci_map_single: [%pa,%zx] -> DAC %llx from %ps\n" , + &paddr, size, ret,__builtin_return_address (0 ));return ret; }
@@ -290,10 +287,10 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, arena->ptes[i + dma_ofs] =mk_iommu_pte (paddr); ret = arena->dma_base + dma_ofs *PAGE_SIZE ; - ret += (unsigned long )cpu_addr & ~PAGE_MASK ; + ret +=offset_in_page (paddr); -DBGA2 ("pci_map_single: [%p,%zx] np %ld -> sg %llx from %ps\n" , - cpu_addr, size, npages, ret,__builtin_return_address (0 )); +DBGA2 ("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n" , + &paddr, size, npages, ret,__builtin_return_address (0 ));return ret; }
@@ -322,19 +319,18 @@ static struct pci_dev *alpha_gendev_to_pci(struct device *dev)return NULL ; } -static dma_addr_t alpha_pci_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction dir, +static dma_addr_t alpha_pci_map_phys (struct device *dev,phys_addr_t phys, +size_t size,enum dma_data_direction dir,unsigned long attrs) {struct pci_dev *pdev =alpha_gendev_to_pci (dev);int dac_allowed; -BUG_ON (dir ==DMA_NONE ); +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; - dac_allowed = pdev ?pci_dac_dma_supported (pdev, pdev->dma_mask) :0 ; -return pci_map_single_1 (pdev, (char *)page_address (page) + offset, - size, dac_allowed); + dac_allowed = pdev ?pci_dac_dma_supported (pdev, pdev->dma_mask) :0 ; +return pci_map_single_1 (pdev, phys, size, dac_allowed); }/* Unmap a single streaming mode DMA translation. The DMA_ADDR and
@@ -343,7 +339,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,the cpu to the buffer are guaranteed to see whatever the device wrote there. */ -static void alpha_pci_unmap_page (struct device *dev,dma_addr_t dma_addr, +static void alpha_pci_unmap_phys (struct device *dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) {
@@ -353,8 +349,6 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,struct pci_iommu_arena *arena;long dma_ofs, npages; -BUG_ON (dir ==DMA_NONE ); -if (dma_addr >= __direct_map_base && dma_addr < __direct_map_base + __direct_map_size) {/* Nothing to do. */
@@ -429,7 +423,7 @@ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size, }memset (cpu_addr,0 , size); - *dma_addrp =pci_map_single_1 (pdev, cpu_addr, size,0 ); + *dma_addrp =pci_map_single_1 (pdev,virt_to_phys (cpu_addr), size,0 );if (*dma_addrp ==DMA_MAPPING_ERROR ) {free_pages ((unsigned long )cpu_addr, order);if (alpha_mv.mv_pci_tbi || (gfp &GFP_DMA ))
@@ -643,9 +637,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,/* Fast path single entry scatterlists. */ if (nents ==1 ) { sg->dma_length = sg->length; - sg->dma_address - =pci_map_single_1 (pdev,SG_ENT_VIRT_ADDRESS (sg), - sg->length, dac_allowed); + sg->dma_address =pci_map_single_1 (pdev,sg_phys (sg), + sg->length, dac_allowed);if (sg->dma_address ==DMA_MAPPING_ERROR )return -EIO ;return 1 ;
@@ -917,8 +910,8 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)const struct dma_map_ops alpha_pci_ops = { .alloc = alpha_pci_alloc_coherent, .free = alpha_pci_free_coherent, - .map_page = alpha_pci_map_page, - .unmap_page = alpha_pci_unmap_page, + .map_phys = alpha_pci_map_phys, + .unmap_phys = alpha_pci_unmap_phys, .map_sg = alpha_pci_map_sg, .unmap_sg = alpha_pci_unmap_sg, .dma_supported = alpha_pci_supported,
Signature · 1 line
2.51.0
PATCH 3/9 parisc: Convert DMA map_page to map_phys interface
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Perform mechanical conversion from .map_page to .map_phys callback.
--- drivers/parisc/ccio-dma.c | 25 +++++++++++++------------ drivers/parisc/sba_iommu.c | 23 ++++++++++++----------- 2 files changed, 25 insertions(+), 23 deletions(-)
drivers/parisc/ccio-dma.c +13 -12
@@ -773,17 +773,18 @@ ccio_map_single(struct device *dev, void *addr, size_t size,static dma_addr_t -ccio_map_page (struct device *dev,struct page *page,unsigned long offset, -size_t size,enum dma_data_direction direction, -unsigned long attrs) +ccio_map_phys (struct device *dev,phys_addr_t phys,size_t size, +enum dma_data_direction direction,unsigned long attrs) { -return ccio_map_single (dev,page_address (page) + offset, size, - direction); +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; + +return ccio_map_single (dev,phys_to_virt (phys), size, direction); }/** -* ccio_unmap_page - Unmap an address range from the IOMMU. +* ccio_unmap_phys - Unmap an address range from the IOMMU. * @dev: The PCI device. * @iova: The start address of the DMA region. * @size: The length of the DMA region.
@@ -791,7 +792,7 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset,* @attrs: attributes */ static void -ccio_unmap_page (struct device *dev,dma_addr_t iova,size_t size, +ccio_unmap_phys (struct device *dev,dma_addr_t iova,size_t size,enum dma_data_direction direction,unsigned long attrs) {struct ioc *ioc;
@@ -873,7 +874,7 @@ static void ccio_free(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) { - ccio_unmap_page(dev, dma_handle, size, 0, 0); + ccio_unmap_phys(dev, dma_handle, size, 0, 0);free_pages ((unsigned long )cpu_addr,get_order (size)); }
@@ -1004,7 +1005,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,#ifdef CCIO_COLLECT_STATS ioc->usg_pages +=sg_dma_len (sglist) >>PAGE_SHIFT ;#endif -ccio_unmap_page (dev,sg_dma_address (sglist), +ccio_unmap_phys (dev,sg_dma_address (sglist),sg_dma_len (sglist), direction,0 ); ++sglist; nents--;
@@ -1017,8 +1018,8 @@ static const struct dma_map_ops ccio_ops = { .dma_supported = ccio_dma_supported, .alloc = ccio_alloc, .free = ccio_free, - .map_page = ccio_map_page, - .unmap_page = ccio_unmap_page, + .map_phys = ccio_map_phys, + .unmap_phys = ccio_unmap_phys, .map_sg = ccio_map_sg, .unmap_sg = ccio_unmap_sg, .get_sgtable = dma_common_get_sgtable,
@@ -1072,7 +1073,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) ioc->msingle_calls, ioc->msingle_pages, (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); -/* KLUGE - unmap_sg calls unmap_page for each mapped page */ +/* KLUGE - unmap_sg calls unmap_phys for each mapped page */ min = ioc->usingle_calls - ioc->usg_calls; max = ioc->usingle_pages - ioc->usg_pages; seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
drivers/parisc/sba_iommu.c +12 -11
@@ -778,17 +778,18 @@ sba_map_single(struct device *dev, void *addr, size_t size,static dma_addr_t -sba_map_page (struct device *dev,struct page *page,unsigned long offset, -size_t size,enum dma_data_direction direction, -unsigned long attrs) +sba_map_phys (struct device *dev,phys_addr_t phys,size_t size, +enum dma_data_direction direction,unsigned long attrs) { -return sba_map_single (dev,page_address (page) + offset, size, - direction); +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; + +return sba_map_single (dev,phys_to_virt (phys), size, direction); }/** -* sba_unmap_page - unmap one IOVA and free resources +* sba_unmap_phys - unmap one IOVA and free resources * @dev: instance of PCI owned by the driver that's asking. * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer.
@@ -798,7 +799,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset,* See Documentation/core-api/dma-api-howto.rst */ static void -sba_unmap_page (struct device *dev,dma_addr_t iova,size_t size, +sba_unmap_phys (struct device *dev,dma_addr_t iova,size_t size,enum dma_data_direction direction,unsigned long attrs) {struct ioc *ioc;
@@ -914,7 +915,7 @@ static void sba_free(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle, unsigned long attrs) { - sba_unmap_page(hwdev, dma_handle, size, 0, 0); + sba_unmap_phys(hwdev, dma_handle, size, 0, 0);free_pages ((unsigned long ) vaddr,get_order (size)); }
@@ -1061,7 +1062,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,while (nents &&sg_dma_len (sglist)) { -sba_unmap_page (dev,sg_dma_address (sglist),sg_dma_len (sglist), +sba_unmap_phys (dev,sg_dma_address (sglist),sg_dma_len (sglist), direction,0 );#ifdef SBA_COLLECT_STATS ioc->usg_pages += ((sg_dma_address (sglist) & ~IOVP_MASK ) +sg_dma_len (sglist) +IOVP_SIZE -1 ) >>PAGE_SHIFT ;
@@ -1085,8 +1086,8 @@ static const struct dma_map_ops sba_ops = { .dma_supported = sba_dma_supported, .alloc = sba_alloc, .free = sba_free, - .map_page = sba_map_page, - .unmap_page = sba_unmap_page, + .map_phys = sba_map_phys, + .unmap_phys = sba_unmap_phys, .map_sg = sba_map_sg, .unmap_sg = sba_unmap_sg, .get_sgtable = dma_common_get_sgtable,
Signature · 1 line
2.51.0
PATCH 4/9 powerpc: Convert to physical address DMA mapping
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Adapt PowerPC DMA to use physical addresses in order to prepare code to removal .map_page and .unmap_page.
--- arch/powerpc/include/asm/iommu.h | 8 +++--- arch/powerpc/kernel/dma-iommu.c | 22 +++++++--------- arch/powerpc/kernel/iommu.c | 14 +++++----- arch/powerpc/platforms/ps3/system-bus.c | 33 ++++++++++++++---------- arch/powerpc/platforms/pseries/ibmebus.c | 15 ++++++----- arch/powerpc/platforms/pseries/vio.c | 21 ++++++++------- 6 files changed, 60 insertions(+), 53 deletions(-)
arch/powerpc/include/asm/iommu.h +4 -4
@@ -274,12 +274,12 @@ extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, unsigned long mask, gfp_t flag, int node);extern void iommu_free_coherent (struct iommu_table *tbl,size_t size,void *vaddr,dma_addr_t dma_handle); -extern dma_addr_t iommu_map_page (struct device *dev,struct iommu_table *tbl, -struct page *page,unsigned long offset, -size_t size,unsigned long mask, +extern dma_addr_t iommu_map_phys (struct device *dev,struct iommu_table *tbl, +phys_addr_t phys,size_t size, +unsigned long mask,enum dma_data_direction direction,unsigned long attrs); -extern void iommu_unmap_page (struct iommu_table *tbl,dma_addr_t dma_handle, +extern void iommu_unmap_phys (struct iommu_table *tbl,dma_addr_t dma_handle,size_t size,enum dma_data_direction direction,unsigned long attrs);
arch/powerpc/kernel/dma-iommu.c +10 -12
@@ -93,28 +93,26 @@ static void dma_iommu_free_coherent(struct device *dev, size_t size,/* Creates TCEs for a user provided buffer. The user buffer must be * contiguous real kernel storage (not vmalloc). The address passed here -* comprises a page address and offset into that page. The dma_addr_t -* returned will point to the same byte within the page as was passed in. +* is a physical address to that page. The dma_addr_t returned will point +* to the same byte within the page as was passed in. */ -static dma_addr_t dma_iommu_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, +static dma_addr_t dma_iommu_map_phys (struct device *dev,phys_addr_t phys, +size_t size,enum dma_data_direction direction,unsigned long attrs) { -return iommu_map_page (dev,get_iommu_table_base (dev), page, offset, - size,dma_get_mask (dev), direction, attrs); +return iommu_map_phys (dev,get_iommu_table_base (dev), phys, size, +dma_get_mask (dev), direction, attrs); } - -static void dma_iommu_unmap_page (struct device *dev,dma_addr_t dma_handle, +static void dma_iommu_unmap_phys (struct device *dev,dma_addr_t dma_handle,size_t size,enum dma_data_direction direction,unsigned long attrs) { -iommu_unmap_page (get_iommu_table_base (dev), dma_handle, size, direction, +iommu_unmap_phys (get_iommu_table_base (dev), dma_handle, size, direction, attrs); } -static int dma_iommu_map_sg (struct device *dev,struct scatterlist *sglist,int nelems,enum dma_data_direction direction,unsigned long attrs)
@@ -211,8 +209,8 @@ const struct dma_map_ops dma_iommu_ops = { .map_sg = dma_iommu_map_sg, .unmap_sg = dma_iommu_unmap_sg, .dma_supported = dma_iommu_dma_supported, - .map_page = dma_iommu_map_page, - .unmap_page = dma_iommu_unmap_page, + .map_phys = dma_iommu_map_phys, + .unmap_phys = dma_iommu_unmap_phys, .get_required_mask = dma_iommu_get_required_mask, .mmap = dma_common_mmap, .get_sgtable = dma_common_get_sgtable,
arch/powerpc/kernel/iommu.c +7 -7
@@ -848,12 +848,12 @@ EXPORT_SYMBOL_GPL(iommu_tce_table_put);/* Creates TCEs for a user provided buffer. The user buffer must be * contiguous real kernel storage (not vmalloc). The address passed here -* comprises a page address and offset into that page. The dma_addr_t -* returned will point to the same byte within the page as was passed in. +* is physical address into that page. The dma_addr_t returned will point +* to the same byte within the page as was passed in. */ -dma_addr_t iommu_map_page (struct device *dev,struct iommu_table *tbl, -struct page *page,unsigned long offset,size_t size, -unsigned long mask,enum dma_data_direction direction, +dma_addr_t iommu_map_phys (struct device *dev,struct iommu_table *tbl, +phys_addr_t phys,size_t size,unsigned long mask, +enum dma_data_direction direction,unsigned long attrs) {dma_addr_t dma_handle =DMA_MAPPING_ERROR ;
@@ -863,7 +863,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,BUG_ON (direction ==DMA_NONE ); - vaddr =page_address (page) + offset; + vaddr =phys_to_virt (phys); uaddr = (unsigned long )vaddr;if (tbl) {
@@ -890,7 +890,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,return dma_handle; } -void iommu_unmap_page (struct iommu_table *tbl,dma_addr_t dma_handle, +void iommu_unmap_phys (struct iommu_table *tbl,dma_addr_t dma_handle,size_t size,enum dma_data_direction direction,unsigned long attrs) {
arch/powerpc/platforms/ps3/system-bus.c +19 -14
@@ -551,18 +551,20 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,/* Creates TCEs for a user provided buffer. The user buffer must be * contiguous real kernel storage (not vmalloc). The address passed here -* comprises a page address and offset into that page. The dma_addr_t -* returned will point to the same byte within the page as was passed in. +* is physical address to that hat page. The dma_addr_t returned will point +* to the same byte within the page as was passed in. */ -static dma_addr_t ps3_sb_map_page (struct device *_dev,struct page *page, -unsigned long offset,size_t size,enum dma_data_direction direction, -unsigned long attrs) +static dma_addr_t ps3_sb_map_phys (struct device *_dev,phys_addr_t phys, +size_t size,enum dma_data_direction direction,unsigned long attrs) {struct ps3_system_bus_device *dev =ps3_dev_to_system_bus_dev (_dev);int result;dma_addr_t bus_addr; -void *ptr =page_address (page) + offset; +void *ptr =phys_to_virt (phys); + +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, &bus_addr,
@@ -577,8 +579,8 @@ static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,return bus_addr; } -static dma_addr_t ps3_ioc0_map_page (struct device *_dev,struct page *page, -unsigned long offset,size_t size, +static dma_addr_t ps3_ioc0_map_phys (struct device *_dev,phys_addr_t phys, +size_t size,enum dma_data_direction direction,unsigned long attrs) {
@@ -586,7 +588,10 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,int result;dma_addr_t bus_addr;u64 iopte_flag; -void *ptr =page_address (page) + offset; +void *ptr =phys_to_virt (phys); + +if (attrs &DMA_ATTR_MMIO ) +return ; iopte_flag =CBE_IOPTE_M ;switch (direction) {
@@ -613,7 +618,7 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,return bus_addr; } -static void ps3_unmap_page (struct device *_dev,dma_addr_t dma_addr, +static void ps3_unmap_phys (struct device *_dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction direction,unsigned long attrs) {struct ps3_system_bus_device *dev =ps3_dev_to_system_bus_dev (_dev);
@@ -690,8 +695,8 @@ static const struct dma_map_ops ps3_sb_dma_ops = { .map_sg = ps3_sb_map_sg, .unmap_sg = ps3_sb_unmap_sg, .dma_supported = ps3_dma_supported, - .map_page = ps3_sb_map_page, - .unmap_page = ps3_unmap_page, + .map_phys = ps3_sb_map_phys, + .unmap_phys = ps3_unmap_phys, .mmap = dma_common_mmap, .get_sgtable = dma_common_get_sgtable, .alloc_pages_op = dma_common_alloc_pages,
@@ -704,8 +709,8 @@ static const struct dma_map_ops ps3_ioc0_dma_ops = { .map_sg = ps3_ioc0_map_sg, .unmap_sg = ps3_ioc0_unmap_sg, .dma_supported = ps3_dma_supported, - .map_page = ps3_ioc0_map_page, - .unmap_page = ps3_unmap_page, + .map_phys = ps3_ioc0_map_phys, + .unmap_phys = ps3_unmap_phys, .mmap = dma_common_mmap, .get_sgtable = dma_common_get_sgtable, .alloc_pages_op = dma_common_alloc_pages,
arch/powerpc/platforms/pseries/ibmebus.c +8 -7
@@ -86,17 +86,18 @@ static void ibmebus_free_coherent(struct device *dev,kfree (vaddr); } -static dma_addr_t ibmebus_map_page (struct device *dev, -struct page *page, -unsigned long offset, +static dma_addr_t ibmebus_map_phys (struct device *dev,phys_addr_t phys,size_t size,enum dma_data_direction direction,unsigned long attrs) { -return (dma_addr_t)(page_address (page) + offset); +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; + +return (dma_addr_t)(phys_to_virt (phys)); } -static void ibmebus_unmap_page(struct device *dev, +static void ibmebus_unmap_phys(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction,
@@ -146,8 +147,8 @@ static const struct dma_map_ops ibmebus_dma_ops = { .unmap_sg = ibmebus_unmap_sg, .dma_supported = ibmebus_dma_supported, .get_required_mask = ibmebus_dma_get_required_mask, - .map_page = ibmebus_map_page, - .unmap_page = ibmebus_unmap_page, + .map_phys = ibmebus_map_phys, + .unmap_phys = ibmebus_unmap_phys, };static int ibmebus_match_path (struct device *dev,const void *data)
arch/powerpc/platforms/pseries/vio.c +12 -9
@@ -512,18 +512,21 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,vio_cmo_dealloc (viodev,roundup (size,PAGE_SIZE )); } -static dma_addr_t vio_dma_iommu_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction direction, -unsigned long attrs) +static dma_addr_t vio_dma_iommu_map_phys (struct device *dev,phys_addr_t phys, +size_t size, +enum dma_data_direction direction, +unsigned long attrs) {struct vio_dev *viodev =to_vio_dev (dev);struct iommu_table *tbl =get_iommu_table_base (dev);dma_addr_t ret =DMA_MAPPING_ERROR ; +if (attrs &DMA_ATTR_MMIO ) +return ret; +if (vio_cmo_alloc (viodev,roundup (size,IOMMU_PAGE_SIZE (tbl)))) goto out_fail; - ret =iommu_map_page (dev, tbl, page, offset, size,dma_get_mask (dev), + ret =iommu_map_phys (dev, tbl, phys, size,dma_get_mask (dev), direction, attrs);if (unlikely (ret ==DMA_MAPPING_ERROR )) goto out_deallocate;
@@ -536,7 +539,7 @@ static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,return DMA_MAPPING_ERROR ; } -static void vio_dma_iommu_unmap_page (struct device *dev,dma_addr_t dma_handle, +static void vio_dma_iommu_unmap_phys (struct device *dev,dma_addr_t dma_handle,size_t size,enum dma_data_direction direction,unsigned long attrs)
@@ -544,7 +547,7 @@ static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,struct vio_dev *viodev =to_vio_dev (dev);struct iommu_table *tbl =get_iommu_table_base (dev); -iommu_unmap_page (tbl, dma_handle, size, direction, attrs); +iommu_unmap_phys (tbl, dma_handle, size, direction, attrs);vio_cmo_dealloc (viodev,roundup (size,IOMMU_PAGE_SIZE (tbl))); }
@@ -605,8 +608,8 @@ static const struct dma_map_ops vio_dma_mapping_ops = { .free = vio_dma_iommu_free_coherent, .map_sg = vio_dma_iommu_map_sg, .unmap_sg = vio_dma_iommu_unmap_sg, - .map_page = vio_dma_iommu_map_page, - .unmap_page = vio_dma_iommu_unmap_page, + .map_phys = vio_dma_iommu_map_phys, + .unmap_phys = vio_dma_iommu_unmap_phys, .dma_supported = dma_iommu_dma_supported, .get_required_mask = dma_iommu_get_required_mask, .mmap = dma_common_mmap,
Signature · 1 line
2.51.0
PATCH 2/9 MIPS/jazzdma: Provide physical address directly
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
MIPS jazz uses physical addresses for mapping pages, so convert it to get them directly from DMA mapping routine.
--- arch/mips/jazz/jazzdma.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
arch/mips/jazz/jazzdma.c +13 -7
@@ -521,18 +521,24 @@ static void jazz_dma_free(struct device *dev, size_t size, void *vaddr,__free_pages (virt_to_page (vaddr),get_order (size)); } -static dma_addr_t jazz_dma_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size,enum dma_data_direction dir, -unsigned long attrs) +static dma_addr_t jazz_dma_map_phys (struct device *dev,phys_addr_t phys, +size_t size,enum dma_data_direction dir,unsigned long attrs) { -phys_addr_t phys =page_to_phys (page) + offset; +if (attrs &DMA_ATTR_MMIO ) +/* +* This check is included because older versions of the code lacked +* MMIO path support, and my ability to test this path is limited. +* However, from a software technical standpoint, there is no restriction, +* as the following code operates solely on physical addresses. +*/ +return DMA_MAPPING_ERROR ;if (!(attrs &DMA_ATTR_SKIP_CPU_SYNC ))arch_sync_dma_for_device (phys, size, dir);return vdma_alloc (phys, size); } -static void jazz_dma_unmap_page (struct device *dev,dma_addr_t dma_addr, +static void jazz_dma_unmap_phys (struct device *dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) {if (!(attrs &DMA_ATTR_SKIP_CPU_SYNC ))
@@ -607,8 +613,8 @@ static void jazz_dma_sync_sg_for_cpu(struct device *dev,const struct dma_map_ops jazz_dma_ops = { .alloc = jazz_dma_alloc, .free = jazz_dma_free, - .map_page = jazz_dma_map_page, - .unmap_page = jazz_dma_unmap_page, + .map_phys = jazz_dma_map_phys, + .unmap_phys = jazz_dma_unmap_phys, .map_sg = jazz_dma_map_sg, .unmap_sg = jazz_dma_unmap_sg, .sync_single_for_cpu = jazz_dma_sync_single_for_cpu,
Signature · 1 line
2.51.0
PATCH 6/9 x86: Use physical address for DMA mapping
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Perform mechanical conversion from DMA .map_page to .map_phys.
--- arch/x86/kernel/amd_gart_64.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
arch/x86/kernel/amd_gart_64.c +10 -9
@@ -222,13 +222,14 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, }/* Map a single area into the IOMMU */ -static dma_addr_t gart_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction dir, +static dma_addr_t gart_map_phys (struct device *dev,phys_addr_t paddr, +size_t size,enum dma_data_direction dir,unsigned long attrs) {unsigned long bus; -phys_addr_t paddr =page_to_phys (page) + offset; + +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ;if (!need_iommu (dev, paddr, size))return paddr;
@@ -242,7 +243,7 @@ static dma_addr_t gart_map_page(struct device *dev, struct page *page,/* * Free a DMA mapping. */ -static void gart_unmap_page (struct device *dev,dma_addr_t dma_addr, +static void gart_unmap_phys (struct device *dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) {
@@ -282,7 +283,7 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,for_each_sg (sg, s, nents, i) {if (!s->dma_length || !s->length)break ; -gart_unmap_page (dev, s->dma_address, s->dma_length, dir,0 ); +gart_unmap_phys (dev, s->dma_address, s->dma_length, dir,0 ); } }
@@ -487,7 +488,7 @@ static void gart_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_addr, unsigned long attrs) { - gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0); + gart_unmap_phys(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0);dma_direct_free (dev, size, vaddr, dma_addr, attrs); }
@@ -668,8 +669,8 @@ static __init int init_amd_gatt(struct agp_kern_info *info)static const struct dma_map_ops gart_dma_ops = { .map_sg = gart_map_sg, .unmap_sg = gart_unmap_sg, - .map_page = gart_map_page, - .unmap_page = gart_unmap_page, + .map_phys = gart_map_phys, + .unmap_phys = gart_unmap_phys, .alloc = gart_alloc_coherent, .free = gart_free_coherent, .mmap = dma_common_mmap,
Signature · 1 line
2.51.0
PATCH 7/9 vdpa: Convert to physical address DMA mapping
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Use physical address directly in DMA mapping flow.
--- drivers/vdpa/vdpa_user/iova_domain.c | 11 +++++------ drivers/vdpa/vdpa_user/iova_domain.h | 8 ++++---- drivers/vdpa/vdpa_user/vduse_dev.c | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 18 deletions(-)
drivers/vdpa/vdpa_user/iova_domain.c +5 -6
@@ -396,17 +396,16 @@ void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,read_unlock (&domain->bounce_lock); } -dma_addr_t vduse_domain_map_page (struct vduse_iova_domain *domain, -struct page *page,unsigned long offset, -size_t size,enum dma_data_direction dir, +dma_addr_t vduse_domain_map_phys (struct vduse_iova_domain *domain, +phys_addr_t pa,size_t size, +enum dma_data_direction dir,unsigned long attrs) {struct iova_domain *iovad = &domain->stream_iovad;unsigned long limit = domain->bounce_size -1 ; -phys_addr_t pa =page_to_phys (page) + offset;dma_addr_t iova =vduse_domain_alloc_iova (iovad, size, limit); -if (!iova) +if (!iova || (attrs &DMA_ATTR_MMIO ))return DMA_MAPPING_ERROR ;if (vduse_domain_init_bounce_map (domain))
@@ -430,7 +429,7 @@ dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,return DMA_MAPPING_ERROR ; } -void vduse_domain_unmap_page (struct vduse_iova_domain *domain, +void vduse_domain_unmap_phys (struct vduse_iova_domain *domain,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) {
drivers/vdpa/vdpa_user/iova_domain.h +4 -4
@@ -53,12 +53,12 @@ void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir); -dma_addr_t vduse_domain_map_page (struct vduse_iova_domain *domain, -struct page *page,unsigned long offset, -size_t size,enum dma_data_direction dir, +dma_addr_t vduse_domain_map_phys (struct vduse_iova_domain *domain, +phys_addr_t phys,size_t size, +enum dma_data_direction dir,unsigned long attrs); -void vduse_domain_unmap_page (struct vduse_iova_domain *domain, +void vduse_domain_unmap_phys (struct vduse_iova_domain *domain,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs);
drivers/vdpa/vdpa_user/vduse_dev.c +10 -8
@@ -834,25 +834,27 @@ static void vduse_dev_sync_single_for_cpu(struct device *dev,vduse_domain_sync_single_for_cpu (domain, dma_addr, size, dir); } -static dma_addr_t vduse_dev_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction dir, +static dma_addr_t vduse_dev_map_phys (struct device *dev,phys_addr_t phys, +size_t size,enum dma_data_direction dir,unsigned long attrs) {struct vduse_dev *vdev =dev_to_vduse (dev);struct vduse_iova_domain *domain = vdev->domain; -return vduse_domain_map_page (domain, page, offset, size, dir, attrs); +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; + +return vduse_domain_map_phys (domain, phys, size, dir, attrs); } -static void vduse_dev_unmap_page (struct device *dev,dma_addr_t dma_addr, +static void vduse_dev_unmap_phys (struct device *dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs) {struct vduse_dev *vdev =dev_to_vduse (dev);struct vduse_iova_domain *domain = vdev->domain; -return vduse_domain_unmap_page (domain, dma_addr, size, dir, attrs); +return vduse_domain_unmap_phys (domain, dma_addr, size, dir, attrs); } static void *vduse_dev_alloc_coherent(struct device *dev, size_t size,
@@ -896,8 +898,8 @@ static size_t vduse_dev_max_mapping_size(struct device *dev)static const struct dma_map_ops vduse_dev_dma_ops = { .sync_single_for_device = vduse_dev_sync_single_for_device, .sync_single_for_cpu = vduse_dev_sync_single_for_cpu, - .map_page = vduse_dev_map_page, - .unmap_page = vduse_dev_unmap_page, + .map_phys = vduse_dev_map_phys, + .unmap_phys = vduse_dev_unmap_phys, .alloc = vduse_dev_alloc_coherent, .free = vduse_dev_free_coherent, .max_mapping_size = vduse_dev_max_mapping_size,
Signature · 1 line
2.51.0
PATCH 5/9 sparc64: Use physical address DMA mapping
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Convert sparc architecture DMA code to use .map_phys callback.
--- arch/sparc/kernel/iommu.c | 16 ++++++------ arch/sparc/kernel/pci_sun4v.c | 16 ++++++------ arch/sparc/mm/io-unit.c | 13 +++++----- arch/sparc/mm/iommu.c | 46 ++++++++++++++++++----------------- 4 files changed, 48 insertions(+), 43 deletions(-)
arch/sparc/kernel/iommu.c +9 -7
@@ -260,9 +260,8 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,free_pages ((unsigned long )cpu, order); } -static dma_addr_t dma_4u_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t sz, -enum dma_data_direction direction, +static dma_addr_t dma_4u_map_phys (struct device *dev,phys_addr_t phys, +size_t sz,enum dma_data_direction direction,unsigned long attrs) {struct iommu *iommu;
@@ -273,13 +272,16 @@ static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,u32 bus_addr, ret;unsigned long iopte_protection; +if (attrs &DMA_ATTR_MMIO ) + goto bad; + iommu = dev->archdata.iommu; strbuf = dev->archdata.stc;if (unlikely (direction ==DMA_NONE )) goto bad_no_ctx; - oaddr = (unsigned long )(page_address (page) + offset); + oaddr = (unsigned long )(phys_to_virt (phys)); npages =IO_PAGE_ALIGN (oaddr + sz) - (oaddr &IO_PAGE_MASK ); npages >>=IO_PAGE_SHIFT ;
@@ -383,7 +385,7 @@ static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, vaddr, ctx, npages); } -static void dma_4u_unmap_page (struct device *dev,dma_addr_t bus_addr, +static void dma_4u_unmap_phys (struct device *dev,dma_addr_t bus_addr,size_t sz,enum dma_data_direction direction,unsigned long attrs) {
@@ -753,8 +755,8 @@ static int dma_4u_supported(struct device *dev, u64 device_mask)static const struct dma_map_ops sun4u_dma_ops = { .alloc = dma_4u_alloc_coherent, .free = dma_4u_free_coherent, - .map_page = dma_4u_map_page, - .unmap_page = dma_4u_unmap_page, + .map_phys = dma_4u_map_phys, + .unmap_phys = dma_4u_unmap_phys, .map_sg = dma_4u_map_sg, .unmap_sg = dma_4u_unmap_sg, .sync_single_for_cpu = dma_4u_sync_single_for_cpu,
arch/sparc/kernel/pci_sun4v.c +9 -7
@@ -352,9 +352,8 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,free_pages ((unsigned long )cpu, order); } -static dma_addr_t dma_4v_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t sz, -enum dma_data_direction direction, +static dma_addr_t dma_4v_map_phys (struct device *dev,phys_addr_t phys, +size_t sz,enum dma_data_direction direction,unsigned long attrs) {struct iommu *iommu;
@@ -367,13 +366,16 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,dma_addr_t bus_addr, ret;long entry; +if (attrs &DMA_ATTR_MMIO ) + goto bad; + iommu = dev->archdata.iommu; atu = iommu->atu;if (unlikely (direction ==DMA_NONE )) goto bad; - oaddr = (unsigned long )(page_address (page) + offset); + oaddr = (unsigned long )(phys_to_virt (phys)); npages =IO_PAGE_ALIGN (oaddr + sz) - (oaddr &IO_PAGE_MASK ); npages >>=IO_PAGE_SHIFT ;
@@ -426,7 +428,7 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,return DMA_MAPPING_ERROR ; } -static void dma_4v_unmap_page (struct device *dev,dma_addr_t bus_addr, +static void dma_4v_unmap_phys (struct device *dev,dma_addr_t bus_addr,size_t sz,enum dma_data_direction direction,unsigned long attrs) {
@@ -686,8 +688,8 @@ static int dma_4v_supported(struct device *dev, u64 device_mask)static const struct dma_map_ops sun4v_dma_ops = { .alloc = dma_4v_alloc_coherent, .free = dma_4v_free_coherent, - .map_page = dma_4v_map_page, - .unmap_page = dma_4v_unmap_page, + .map_phys = dma_4v_map_phys, + .unmap_phys = dma_4v_unmap_phys, .map_sg = dma_4v_map_sg, .unmap_sg = dma_4v_unmap_sg, .dma_supported = dma_4v_supported,
arch/sparc/mm/io-unit.c +6 -7
@@ -142,11 +142,10 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);return vaddr; } -static dma_addr_t iounit_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t len,enum dma_data_direction dir, -unsigned long attrs) +static dma_addr_t iounit_map_phys (struct device *dev,phys_addr_t phys, +size_t len,enum dma_data_direction dir,unsigned long attrs) { -void *vaddr =page_address (page) + offset; +void *vaddr =phys_to_virt (phys);struct iounit_struct *iounit = dev->archdata.iommu;unsigned long ret, flags;
@@ -178,7 +177,7 @@ static int iounit_map_sg(struct device *dev, struct scatterlist *sgl, int nents,return nents; } -static void iounit_unmap_page (struct device *dev,dma_addr_t vaddr,size_t len, +static void iounit_unmap_phys (struct device *dev,dma_addr_t vaddr,size_t len,enum dma_data_direction dir,unsigned long attrs) {struct iounit_struct *iounit = dev->archdata.iommu;
@@ -279,8 +278,8 @@ static const struct dma_map_ops iounit_dma_ops = { .alloc = iounit_alloc, .free = iounit_free, #endif - .map_page = iounit_map_page, - .unmap_page = iounit_unmap_page, + .map_phys = iounit_map_phys, + .unmap_phys = iounit_unmap_phys, .map_sg = iounit_map_sg, .unmap_sg = iounit_unmap_sg, };
arch/sparc/mm/iommu.c +24 -22
109 lines not on this page · raw message
Signature · 1 line
2.51.0
PATCH 9/9 dma-mapping: remove unused map_page callback
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
After conversion of arch code to use physical address mapping, there are no users of .map_page() and .unmap_page() callbacks, so let's remove them.
--- include/linux/dma-map-ops.h | 7 ------- kernel/dma/mapping.c | 12 ------------ kernel/dma/ops_helpers.c | 8 +------- 3 files changed, 1 insertion(+), 26 deletions(-)
include/linux/dma-map-ops.h +0 -7
@@ -31,13 +31,6 @@ struct dma_map_ops { void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs); -dma_addr_t (*map_page)(struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction dir,unsigned long attrs); -void (*unmap_page)(struct device *dev,dma_addr_t dma_handle, -size_t size,enum dma_data_direction dir, -unsigned long attrs); -dma_addr_t (*map_phys)(struct device *dev,phys_addr_t phys,size_t size,enum dma_data_direction dir,unsigned long attrs);
kernel/dma/mapping.c +0 -12
@@ -171,16 +171,6 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size, addr =iommu_dma_map_phys (dev, phys, size, dir, attrs); else if (ops->map_phys) addr = ops->map_phys (dev, phys, size, dir, attrs); - else if (!is_mmio && ops->map_page) { -struct page *page =phys_to_page (phys); -size_t offset =offset_in_page (phys); - -/* -* The dma_ops API contract for ops->map_page() requires -* kmappable memory. -*/ - addr = ops->map_page (dev, page, offset, size, dir, attrs); - }if (!is_mmio)kmsan_handle_dma (phys, size, dir);
@@ -222,8 +212,6 @@ void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,iommu_dma_unmap_phys (dev, addr, size, dir, attrs); else if (ops->unmap_phys) ops->unmap_phys(dev, addr, size, dir, attrs); - else - ops->unmap_page(dev, addr, size, dir, attrs);trace_dma_unmap_phys (dev ,addr ,size ,dir ,attrs );debug_dma_unmap_phys (dev, addr, size, dir); }
kernel/dma/ops_helpers.c +1 -7
@@ -76,11 +76,8 @@ struct page *dma_common_alloc_pages(struct device *dev, size_t size,if (use_dma_iommu (dev)) *dma_handle =iommu_dma_map_phys (dev, phys, size, dir,DMA_ATTR_SKIP_CPU_SYNC ); -else if (ops->map_phys) - *dma_handle = ops->map_phys (dev, phys, size, dir, -DMA_ATTR_SKIP_CPU_SYNC );else - *dma_handle = ops->map_page (dev, page,0 , size, dir, + *dma_handle = ops->map_phys (dev, phys, size, dir,DMA_ATTR_SKIP_CPU_SYNC );if (*dma_handle ==DMA_MAPPING_ERROR ) {dma_free_contiguous (dev, page, size);
@@ -102,8 +99,5 @@ void dma_common_free_pages(struct device *dev, size_t size, struct page *page,else if (ops->unmap_phys) ops->unmap_phys (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); }
Signature · 1 line
2.51.0
PATCH 8/9 xen: swiotlb: Convert mapping routine to rely on physical address
In reply to Leon RomanovskyFrom: Leon Romanovsky <[email protected]>
Switch to .map_phys callback instead of .map_page.
--- drivers/xen/grant-dma-ops.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
drivers/xen/grant-dma-ops.c +12 -8
@@ -163,18 +163,22 @@ static void xen_grant_dma_free_pages(struct device *dev, size_t size,xen_grant_dma_free (dev, size,page_to_virt (vaddr), dma_handle,0 ); } -static dma_addr_t xen_grant_dma_map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, +static dma_addr_t xen_grant_dma_map_phys (struct device *dev,phys_addr_t phys, +size_t size,enum dma_data_direction dir,unsigned long attrs) {struct xen_grant_dma_data *data; +unsigned long offset =offset_in_page (phys);unsigned long dma_offset =xen_offset_in_page (offset), pfn_offset =XEN_PFN_DOWN (offset);unsigned int i, n_pages =XEN_PFN_UP (dma_offset + size);grant_ref_t grant;dma_addr_t dma_handle; +if (attrs &DMA_ATTR_MMIO ) +return DMA_MAPPING_ERROR ; +if (WARN_ON (dir ==DMA_NONE ))return DMA_MAPPING_ERROR ;
@@ -190,7 +194,7 @@ static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page,for (i =0 ; i < n_pages; i++) {gnttab_grant_foreign_access_ref (grant + i, data->backend_domid, -pfn_to_gfn (page_to_xen_pfn (page) + i + pfn_offset), +pfn_to_gfn (page_to_xen_pfn (phys_to_page (phys)) + i + pfn_offset), dir ==DMA_TO_DEVICE ); }
@@ -199,7 +203,7 @@ static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page,return dma_handle; } -static void xen_grant_dma_unmap_page (struct device *dev,dma_addr_t dma_handle, +static void xen_grant_dma_unmap_phys (struct device *dev,dma_addr_t dma_handle,size_t size,enum dma_data_direction dir,unsigned long attrs) {
@@ -242,7 +246,7 @@ static void xen_grant_dma_unmap_sg(struct device *dev, struct scatterlist *sg,return ;for_each_sg (sg, s, nents, i) -xen_grant_dma_unmap_page (dev, s->dma_address,sg_dma_len (s), dir, +xen_grant_dma_unmap_phys (dev, s->dma_address,sg_dma_len (s), dir, attrs); }
@@ -257,7 +261,7 @@ static int xen_grant_dma_map_sg(struct device *dev, struct scatterlist *sg,return -EINVAL ;for_each_sg (sg, s, nents, i) { - s->dma_address =xen_grant_dma_map_page (dev,sg_page (s), s->offset, + s->dma_address =xen_grant_dma_map_phys (dev,sg_phys (s), s->length, dir, attrs);if (s->dma_address ==DMA_MAPPING_ERROR ) goto out;
@@ -286,8 +290,8 @@ static const struct dma_map_ops xen_grant_dma_ops = { .free_pages = xen_grant_dma_free_pages, .mmap = dma_common_mmap, .get_sgtable = dma_common_get_sgtable, - .map_page = xen_grant_dma_map_page, - .unmap_page = xen_grant_dma_unmap_page, + .map_phys = xen_grant_dma_map_phys, + .unmap_phys = xen_grant_dma_unmap_phys, .map_sg = xen_grant_dma_map_sg, .unmap_sg = xen_grant_dma_unmap_sg, .dma_supported = xen_grant_dma_supported,
Signature · 1 line
2.51.0
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
In reply to Leon RomanovskyQuoted 5 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
Alpha doesn't need struct *page and can perform mapping based on physical addresses. So convert it to implement new .map_phys callback.
Hi,
SInce this patch affects the Alpha platform I got curious and decided to try it out. The patch series requires some preparatory patches. Leon provided me with links to his dmabuf-vfio branch, which had the patches (and some prerequisite stuff) applied already.
Based on the dmabuf-vfio branch, I've built a kernel and tested it on my ES40 Alphaserver, the kernel booted fine but after a while of moderate filesystem load I started seeing some ext3/4 related error messages in the system logs. Rebooting with my old kernel into single user mode, I was able to recover the filesystem using fsck. Clearly this set of patches breaks things (at least on Alpha).
I haven't yet dug any deeper into the root causes of the file system corruptions and I've only tested this on Alpha, maybe there has been more testing done on other platforms targeted by this set of patches?
Regards
Magnus Lindholm
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 15 lines · Magnus Lindholm
Quoted 5 lines · Leon Romanovsky
From: Leon Romanovsky <[email protected]>
Alpha doesn't need struct *page and can perform mapping based on physical addresses. So convert it to implement new .map_phys callback.
Hi,
SInce this patch affects the Alpha platform I got curious and decided to try it out. The patch series requires some preparatory patches. Leon provided me with links to his dmabuf-vfio branch, which had the patches (and some prerequisite stuff) applied already.
Quoted 6 lines
Based on the dmabuf-vfio branch, I've built a kernel and tested it on my ES40 Alphaserver, the kernel booted fine but after a while of moderate filesystem load I started seeing some ext3/4 related error messages in the system logs. Rebooting with my old kernel into single user mode, I was able to recover the filesystem using fsck. Clearly this set of patches breaks things (at least on Alpha).
I will try to setup Alpha architecture in QEMU in following days, but would like to ask first. Did you test alpha on clean v6.17-rc5 (without my patches) as a reference?
Thanks
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 5 lines
I will try to setup Alpha architecture in QEMU in following days, but would like to ask first. Did you test alpha on clean v6.17-rc5 (without my patches) as a reference?
I'm running now on a fresh git pull from today so it's more like a 6.17-rc7. So no problems running the latest git at least. I can dig deeper into this to see if we can figure this one out. First of all, is this alpha specific?
Regards
Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 9 lines · Magnus Lindholm
Quoted 5 lines
I will try to setup Alpha architecture in QEMU in following days, but would like to ask first. Did you test alpha on clean v6.17-rc5 (without my patches) as a reference?
I'm running now on a fresh git pull from today so it's more like a 6.17-rc7. So no problems running the latest git at least. I can dig deeper into this to see if we can figure this one out. First of all, is this alpha specific?
I spent a bit of time looking at the alpha patch and could not spot a typo, it looked OK to me. I was worried for a bit that virt_to_phys() vs __pa() were different, but I could not find a difference.
Suggest testing the same branch with the alpha patch reverted just to rule out any issue in the core code. If it reproduces suggest to bisect Leon's branch.
Thanks,
Jason
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 4 lines
Suggest testing the same branch with the alpha patch reverted just to rule out any issue in the core code. If it reproduces suggest to bisect Leon's branch.
I can try to revert just the patch containing the alpha-specific stuff and see what happens and then, as you say, maybe do a bisect from there. First I'll just try the same kernel again a few times more just to make sure that this is really reproducible.
/Magnus
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 3 lines
Quoted 3 lines
Suggest testing the same branch with the alpha patch reverted just to rule out any issue in the core code. If it reproduces suggest to bisect Leon's branch.
Hi again, I've booted up the ES40 again with the kernel build from Leons branch, it boots up but message log is full off messages like "EXT4-fs error (device sda4): ext4_find_extent:939: inode #16257327: comm init: pblk 65114257 bad header/extent:
invalid magic"
The filesystem is broken after just booting with the kernel. This time fsck did not fix it, I needed to re-install gentoo stage3. So it's for sure reproducible as well as destructive. It's not possible to revert all the commits individually, since this will leave the source tree in a state where the kernel doesn't build. I've started off by reverting the following commits:
e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)
d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)
3cd47242d513050d7a81ac6e7020fd3ef5462ad4
(block-dma: properly take MMIO path)
7950995bef32aa7e5f74699c7d0fdac41d2dad14
(block-dma: migrate to dma_map_phys instead of map_page)
After reverting the above commits, I'm able to build a working kernel, that is, no filesystem corruption occurs. I'll take a closer look at this after the weekend.
Regards
Magnus
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 4 lines
After reverting the above commits, I'm able to build a working kernel, that is, no filesystem corruption occurs. I'll take a closer look at this after the weekend.
Short update, It is enough to revert the following commits, in order to have a working kernel on alpha:
e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unused map_page callback)
d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)
/Magnus
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 5 lines · Magnus Lindholm
Quoted 4 lines
After reverting the above commits, I'm able to build a working kernel, that is, no filesystem corruption occurs. I'll take a closer look at this after the weekend.
Quoted 8 lines
Short update, It is enough to revert the following commits, in order to have a working kernel on alpha:
e78a9d72517a88faa6f16dab4d1c6f966ed378ae
(dma-mapping: remove unusedmap_pagecallback)
d459e3b80ad1c81bf596d63d2e3347cf8c7bb0d9
(alpha: Convert mapping routine to rely on physical address)
Thanks for the effort.
Can you please check the following change instead of reverting the patches?
arch/alpha/kernel/pci_iommu.c +2 -1
@@ -229,6 +229,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size, {struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;dma_addr_t max_dma = pdev ? pdev->dma_mask :ISA_DMA_MASK ; +unsigned long offset =offset_in_page (paddr);struct pci_iommu_arena *arena;long npages, dma_ofs, i;dma_addr_t ret;
@@ -287,7 +288,7 @@ pci_map_single_1(struct pci_dev *pdev, phys_addr_t paddr, size_t size, arena->ptes[i + dma_ofs] =mk_iommu_pte (paddr); ret = arena->dma_base + dma_ofs *PAGE_SIZE ; - ret +=offset_in_page (paddr); + ret += offset;DBGA2 ("pci_map_single: [%pa,%zx] np %ld -> sg %llx from %ps\n" , &paddr, size, npages, ret,__builtin_return_address (0 ));
~
Quoted 3 lines
/Magnus
Magnus Lindholm
maintainerRe: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 4 lines
Thanks for the effort.
Can you please check the following change instead of reverting the patches?
No problem, happy to assist. I think this did the trick! preliminary testing shows
that this now works on alpha! I guess the offset information in paddr was lost by doing "paddr &= PAGE_MASK" before retrieving the offset, well spotted!
I'll keep running the system with some load to make sure there is nothing else we haven't spotted yet, but so far so good. I'll keep you posted.
Will you be putting out a v2 of this patchset with these updates?
Regards
Magnus Lindholm
Re: [PATCH 1/9] alpha: Convert mapping routine to rely on physical address
Quoted 10 lines · Magnus Lindholm
Quoted 4 lines
Thanks for the effort.
Can you please check the following change instead of reverting the patches?
No problem, happy to assist. I think this did the trick! preliminary testing shows
that this now works on alpha! I guess the offset information in paddr was lost by doing "paddr &=PAGE_MASK" before retrieving the offset, well spotted!
Quoted 4 lines
I'll keep running the system with some load to make sure there is nothing else we haven't spotted yet, but so far so good. I'll keep you posted.
Will you be putting out a v2 of this patchset with these updates?
Yes, will try to send today.
Thanks again for your help.
Quoted 4 lines
Regards
Magnus Lindholm