[PATCH 02/18] dma-mapping: move the PCI P2PDMA mapping helpers to pci-p2pdma.h
Bjorn Helgaas
helgaas at kernel.org
Tue Oct 29 08:11:04 PDT 2024
On Sun, Oct 27, 2024 at 04:21:02PM +0200, Leon Romanovsky wrote:
> From: Christoph Hellwig <hch at lst.de>
>
> To support the upcoming non-scatterlist mapping helpers, we need to go
> back to have them called outside of the DMA API. Thus move them out of
> dma-map-ops.h, which is only for DMA API implementations to pci-p2pdma.h,
> which is for driver use.
>
> Note that the core helper is still not exported as the mapping is
> expected to be done only by very highlevel subsystem code at least for
> now.
>
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> Signed-off-by: Leon Romanovsky <leonro at nvidia.com>
Acked-by: Bjorn Helgaas <bhelgaas at google.com>
> ---
> drivers/iommu/dma-iommu.c | 1 +
> include/linux/dma-map-ops.h | 84 -------------------------------------
> include/linux/pci-p2pdma.h | 84 +++++++++++++++++++++++++++++++++++++
> kernel/dma/direct.c | 1 +
> 4 files changed, 86 insertions(+), 84 deletions(-)
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 6e50023c8112..c422e36c0d66 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -26,6 +26,7 @@
> #include <linux/mutex.h>
> #include <linux/of_iommu.h>
> #include <linux/pci.h>
> +#include <linux/pci-p2pdma.h>
> #include <linux/scatterlist.h>
> #include <linux/spinlock.h>
> #include <linux/swiotlb.h>
> diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
> index 49edcbda19d1..6ee626e50708 100644
> --- a/include/linux/dma-map-ops.h
> +++ b/include/linux/dma-map-ops.h
> @@ -435,88 +435,4 @@ static inline void debug_dma_dump_mappings(struct device *dev)
>
> extern const struct dma_map_ops dma_dummy_ops;
>
> -enum pci_p2pdma_map_type {
> - /*
> - * PCI_P2PDMA_MAP_UNKNOWN: Used internally for indicating the mapping
> - * type hasn't been calculated yet. Functions that return this enum
> - * never return this value.
> - */
> - PCI_P2PDMA_MAP_UNKNOWN = 0,
> -
> - /*
> - * Not a PCI P2PDMA transfer.
> - */
> - PCI_P2PDMA_MAP_NONE,
> -
> - /*
> - * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will
> - * traverse the host bridge and the host bridge is not in the
> - * allowlist. DMA Mapping routines should return an error when
> - * this is returned.
> - */
> - PCI_P2PDMA_MAP_NOT_SUPPORTED,
> -
> - /*
> - * PCI_P2PDMA_BUS_ADDR: Indicates that two devices can talk to
> - * each other directly through a PCI switch and the transaction will
> - * not traverse the host bridge. Such a mapping should program
> - * the DMA engine with PCI bus addresses.
> - */
> - PCI_P2PDMA_MAP_BUS_ADDR,
> -
> - /*
> - * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: Indicates two devices can talk
> - * to each other, but the transaction traverses a host bridge on the
> - * allowlist. In this case, a normal mapping either with CPU physical
> - * addresses (in the case of dma-direct) or IOVA addresses (in the
> - * case of IOMMUs) should be used to program the DMA engine.
> - */
> - PCI_P2PDMA_MAP_THRU_HOST_BRIDGE,
> -};
> -
> -struct pci_p2pdma_map_state {
> - struct dev_pagemap *pgmap;
> - enum pci_p2pdma_map_type map;
> - u64 bus_off;
> -};
> -
> -/* helper for pci_p2pdma_state(), do not use directly */
> -void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state,
> - struct device *dev, struct page *page);
> -
> -/**
> - * pci_p2pdma_state - check the P2P transfer state of a page
> - * @state: P2P state structure
> - * @dev: device to transfer to/from
> - * @page: page to map
> - *
> - * Check if @page is a PCI P2PDMA page, and if yes of what kind. Returns the
> - * map type, and updates @state with all information needed for a P2P transfer.
> - */
> -static inline enum pci_p2pdma_map_type
> -pci_p2pdma_state(struct pci_p2pdma_map_state *state, struct device *dev,
> - struct page *page)
> -{
> - if (IS_ENABLED(CONFIG_PCI_P2PDMA) && is_pci_p2pdma_page(page)) {
> - if (state->pgmap != page->pgmap)
> - __pci_p2pdma_update_state(state, dev, page);
> - return state->map;
> - }
> - return PCI_P2PDMA_MAP_NONE;
> -}
> -
> -/**
> - * pci_p2pdma_bus_addr_map - map a PCI_P2PDMA_MAP_BUS_ADDR P2P transfer
> - * @state: P2P state structure
> - * @paddr: physical address to map
> - *
> - * Map a physically contigous PCI_P2PDMA_MAP_BUS_ADDR transfer.
> - */
> -static inline dma_addr_t
> -pci_p2pdma_bus_addr_map(struct pci_p2pdma_map_state *state, phys_addr_t paddr)
> -{
> - WARN_ON_ONCE(state->map != PCI_P2PDMA_MAP_BUS_ADDR);
> - return paddr + state->bus_off;
> -}
> -
> #endif /* _LINUX_DMA_MAP_OPS_H */
> diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h
> index 2c07aa6b7665..66b71f60a811 100644
> --- a/include/linux/pci-p2pdma.h
> +++ b/include/linux/pci-p2pdma.h
> @@ -104,4 +104,88 @@ static inline struct pci_dev *pci_p2pmem_find(struct device *client)
> return pci_p2pmem_find_many(&client, 1);
> }
>
> +enum pci_p2pdma_map_type {
> + /*
> + * PCI_P2PDMA_MAP_UNKNOWN: Used internally for indicating the mapping
> + * type hasn't been calculated yet. Functions that return this enum
> + * never return this value.
> + */
> + PCI_P2PDMA_MAP_UNKNOWN = 0,
> +
> + /*
> + * Not a PCI P2PDMA transfer.
> + */
> + PCI_P2PDMA_MAP_NONE,
> +
> + /*
> + * PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will
> + * traverse the host bridge and the host bridge is not in the
> + * allowlist. DMA Mapping routines should return an error when
> + * this is returned.
> + */
> + PCI_P2PDMA_MAP_NOT_SUPPORTED,
> +
> + /*
> + * PCI_P2PDMA_BUS_ADDR: Indicates that two devices can talk to
> + * each other directly through a PCI switch and the transaction will
> + * not traverse the host bridge. Such a mapping should program
> + * the DMA engine with PCI bus addresses.
> + */
> + PCI_P2PDMA_MAP_BUS_ADDR,
> +
> + /*
> + * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: Indicates two devices can talk
> + * to each other, but the transaction traverses a host bridge on the
> + * allowlist. In this case, a normal mapping either with CPU physical
> + * addresses (in the case of dma-direct) or IOVA addresses (in the
> + * case of IOMMUs) should be used to program the DMA engine.
> + */
> + PCI_P2PDMA_MAP_THRU_HOST_BRIDGE,
> +};
> +
> +struct pci_p2pdma_map_state {
> + struct dev_pagemap *pgmap;
> + enum pci_p2pdma_map_type map;
> + u64 bus_off;
> +};
> +
> +/* helper for pci_p2pdma_state(), do not use directly */
> +void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state,
> + struct device *dev, struct page *page);
> +
> +/**
> + * pci_p2pdma_state - check the P2P transfer state of a page
> + * @state: P2P state structure
> + * @dev: device to transfer to/from
> + * @page: page to map
> + *
> + * Check if @page is a PCI P2PDMA page, and if yes of what kind. Returns the
> + * map type, and updates @state with all information needed for a P2P transfer.
> + */
> +static inline enum pci_p2pdma_map_type
> +pci_p2pdma_state(struct pci_p2pdma_map_state *state, struct device *dev,
> + struct page *page)
> +{
> + if (IS_ENABLED(CONFIG_PCI_P2PDMA) && is_pci_p2pdma_page(page)) {
> + if (state->pgmap != page->pgmap)
> + __pci_p2pdma_update_state(state, dev, page);
> + return state->map;
> + }
> + return PCI_P2PDMA_MAP_NONE;
> +}
> +
> +/**
> + * pci_p2pdma_bus_addr_map - map a PCI_P2PDMA_MAP_BUS_ADDR P2P transfer
> + * @state: P2P state structure
> + * @paddr: physical address to map
> + *
> + * Map a physically contigous PCI_P2PDMA_MAP_BUS_ADDR transfer.
> + */
> +static inline dma_addr_t
> +pci_p2pdma_bus_addr_map(struct pci_p2pdma_map_state *state, phys_addr_t paddr)
> +{
> + WARN_ON_ONCE(state->map != PCI_P2PDMA_MAP_BUS_ADDR);
> + return paddr + state->bus_off;
> +}
> +
> #endif /* _LINUX_PCI_P2P_H */
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index a793400161c2..47e124561fff 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -13,6 +13,7 @@
> #include <linux/vmalloc.h>
> #include <linux/set_memory.h>
> #include <linux/slab.h>
> +#include <linux/pci-p2pdma.h>
> #include "direct.h"
>
> /*
> --
> 2.46.2
>
More information about the Linux-nvme
mailing list