Commit c76c067e authored by Niklas Schnelle's avatar Niklas Schnelle Committed by Joerg Roedel
Browse files

s390/pci: Use dma-iommu layer



While s390 already has a standard IOMMU driver and previous changes have
added I/O TLB flushing operations this driver is currently only used for
user-space PCI access such as vfio-pci. For the DMA API s390 instead
utilizes its own implementation in arch/s390/pci/pci_dma.c which drives
the same hardware and shares some code but requires a complex and
fragile hand over between DMA API and IOMMU API use of a device and
despite code sharing still leads to significant duplication and
maintenance effort. Let's utilize the common code DMAP API
implementation from drivers/iommu/dma-iommu.c instead allowing us to
get rid of arch/s390/pci/pci_dma.c.

Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Link: https://lore.kernel.org/r/20230928-dma_iommu-v13-3-9e5fc4dacc36@linux.ibm.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent b6f88870
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -2220,7 +2220,7 @@
			  forcing Dual Address Cycle for PCI cards supporting
			  greater than 32-bit addressing.

	iommu.strict=	[ARM64, X86] Configure TLB invalidation behaviour
	iommu.strict=	[ARM64, X86, S390] Configure TLB invalidation behaviour
			Format: { "0" | "1" }
			0 - Lazy mode.
			  Request that DMA unmap operations use deferred
@@ -5611,9 +5611,10 @@
	s390_iommu=	[HW,S390]
			Set s390 IOTLB flushing mode
		strict
			With strict flushing every unmap operation will result in
			an IOTLB flush. Default is lazy flushing before reuse,
			which is faster.
			With strict flushing every unmap operation will result
			in an IOTLB flush. Default is lazy flushing before
			reuse, which is faster. Deprecated, equivalent to
			iommu.strict=1.

	s390_iommu_aperture=	[KNL,S390]
			Specifies the size of the per device DMA address space
+0 −7
Original line number Diff line number Diff line
@@ -159,13 +159,6 @@ struct zpci_dev {
	unsigned long	*dma_table;
	int		tlb_refresh;

	spinlock_t	iommu_bitmap_lock;
	unsigned long	*iommu_bitmap;
	unsigned long	*lazy_bitmap;
	unsigned long	iommu_size;
	unsigned long	iommu_pages;
	unsigned int	next_bit;

	struct iommu_device iommu_dev;  /* IOMMU core handle */

	char res_name[16];
+3 −0
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ struct clp_fh_list_entry {
#define CLP_UTIL_STR_LEN	64
#define CLP_PFIP_NR_SEGMENTS	4

/* PCI function type numbers */
#define PCI_FUNC_TYPE_ISM	0x5	/* ISM device */

extern bool zpci_unique_uid;

struct clp_rsp_slpc_pci {
+10 −111
Original line number Diff line number Diff line
@@ -82,117 +82,16 @@ enum zpci_ioat_dtype {
#define ZPCI_TABLE_VALID_MASK		0x20
#define ZPCI_TABLE_PROT_MASK		0x200

static inline unsigned int calc_rtx(dma_addr_t ptr)
{
	return ((unsigned long) ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
}

static inline unsigned int calc_sx(dma_addr_t ptr)
{
	return ((unsigned long) ptr >> ZPCI_ST_SHIFT) & ZPCI_INDEX_MASK;
}

static inline unsigned int calc_px(dma_addr_t ptr)
{
	return ((unsigned long) ptr >> PAGE_SHIFT) & ZPCI_PT_MASK;
}

static inline void set_pt_pfaa(unsigned long *entry, phys_addr_t pfaa)
{
	*entry &= ZPCI_PTE_FLAG_MASK;
	*entry |= (pfaa & ZPCI_PTE_ADDR_MASK);
}

static inline void set_rt_sto(unsigned long *entry, phys_addr_t sto)
{
	*entry &= ZPCI_RTE_FLAG_MASK;
	*entry |= (sto & ZPCI_RTE_ADDR_MASK);
	*entry |= ZPCI_TABLE_TYPE_RTX;
}

static inline void set_st_pto(unsigned long *entry, phys_addr_t pto)
{
	*entry &= ZPCI_STE_FLAG_MASK;
	*entry |= (pto & ZPCI_STE_ADDR_MASK);
	*entry |= ZPCI_TABLE_TYPE_SX;
}

static inline void validate_rt_entry(unsigned long *entry)
{
	*entry &= ~ZPCI_TABLE_VALID_MASK;
	*entry &= ~ZPCI_TABLE_OFFSET_MASK;
	*entry |= ZPCI_TABLE_VALID;
	*entry |= ZPCI_TABLE_LEN_RTX;
}

static inline void validate_st_entry(unsigned long *entry)
{
	*entry &= ~ZPCI_TABLE_VALID_MASK;
	*entry |= ZPCI_TABLE_VALID;
}

static inline void invalidate_pt_entry(unsigned long *entry)
{
	WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID);
	*entry &= ~ZPCI_PTE_VALID_MASK;
	*entry |= ZPCI_PTE_INVALID;
}

static inline void validate_pt_entry(unsigned long *entry)
{
	WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID);
	*entry &= ~ZPCI_PTE_VALID_MASK;
	*entry |= ZPCI_PTE_VALID;
}

static inline void entry_set_protected(unsigned long *entry)
{
	*entry &= ~ZPCI_TABLE_PROT_MASK;
	*entry |= ZPCI_TABLE_PROTECTED;
}

static inline void entry_clr_protected(unsigned long *entry)
{
	*entry &= ~ZPCI_TABLE_PROT_MASK;
	*entry |= ZPCI_TABLE_UNPROTECTED;
}

static inline int reg_entry_isvalid(unsigned long entry)
{
	return (entry & ZPCI_TABLE_VALID_MASK) == ZPCI_TABLE_VALID;
}

static inline int pt_entry_isvalid(unsigned long entry)
{
	return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID;
}

static inline unsigned long *get_rt_sto(unsigned long entry)
{
	if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX)
		return phys_to_virt(entry & ZPCI_RTE_ADDR_MASK);
	else
		return NULL;

}

static inline unsigned long *get_st_pto(unsigned long entry)
{
	if ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX)
		return phys_to_virt(entry & ZPCI_STE_ADDR_MASK);
	else
		return NULL;
}

/* Prototypes */
void dma_free_seg_table(unsigned long);
unsigned long *dma_alloc_cpu_table(gfp_t gfp);
void dma_cleanup_tables(unsigned long *);
unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr,
				  gfp_t gfp);
void dma_update_cpu_trans(unsigned long *entry, phys_addr_t page_addr, int flags);

extern const struct dma_map_ops s390_pci_dma_ops;
struct zpci_iommu_ctrs {
	atomic64_t		mapped_pages;
	atomic64_t		unmapped_pages;
	atomic64_t		global_rpcits;
	atomic64_t		sync_map_rpcits;
	atomic64_t		sync_rpcits;
};

struct zpci_dev;

struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev);

#endif
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
# Makefile for the s390 PCI subsystem.
#

obj-$(CONFIG_PCI)	+= pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
obj-$(CONFIG_PCI)	+= pci.o pci_irq.o pci_clp.o pci_sysfs.o \
			   pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
			   pci_bus.o pci_kvm_hook.o
obj-$(CONFIG_PCI_IOV)	+= pci_iov.o
Loading