Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8128f23c authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Joerg Roedel
Browse files

iommu/s390: Add iommu api for s390 pci devices



This adds an IOMMU API implementation for s390 PCI devices.

Reviewed-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 049e6dde
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -8943,6 +8943,13 @@ F: drivers/s390/net/*iucv*
F:	include/net/iucv/
F:	net/iucv/

S390 IOMMU (PCI)
M:	Gerald Schaefer <gerald.schaefer@de.ibm.com>
L:	linux-s390@vger.kernel.org
W:	http://www.ibm.com/developerworks/linux/linux390/
S:	Supported
F:	drivers/iommu/s390-iommu.c

S3C24XX SD/MMC Driver
M:	Ben Dooks <ben-linux@fluff.org>
L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+1 −0
Original line number Diff line number Diff line
@@ -582,6 +582,7 @@ menuconfig PCI
	bool "PCI support"
	select HAVE_DMA_ATTRS
	select PCI_MSI
	select IOMMU_SUPPORT
	help
	  Enable PCI support.

+4 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ struct zpci_bar_struct {
	u8		size;		/* order 2 exponent */
};

struct s390_domain;

/* Private data per function */
struct zpci_dev {
	struct pci_dev	*pdev;
@@ -118,6 +120,8 @@ struct zpci_dev {

	struct dentry	*debugfs_dev;
	struct dentry	*debugfs_perf;

	struct s390_domain *s390_domain; /* s390 IOMMU domain data */
};

static inline bool zdev_enabled(struct zpci_dev *zdev)
+4 −1
Original line number Diff line number Diff line
@@ -192,5 +192,8 @@ static inline unsigned long *get_st_pto(unsigned long entry)
/* Prototypes */
int zpci_dma_init_device(struct zpci_dev *);
void zpci_dma_exit_device(struct zpci_dev *);

void dma_free_seg_table(unsigned long);
unsigned long *dma_alloc_cpu_table(void);
void dma_cleanup_tables(unsigned long *);
void dma_update_cpu_trans(unsigned long *, void *, dma_addr_t, int);
#endif
+25 −12
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ static int zpci_refresh_global(struct zpci_dev *zdev)
				  zdev->iommu_pages * PAGE_SIZE);
}

static unsigned long *dma_alloc_cpu_table(void)
unsigned long *dma_alloc_cpu_table(void)
{
	unsigned long *table, *entry;

@@ -114,12 +114,12 @@ static unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr
	return &pto[px];
}

static void dma_update_cpu_trans(struct zpci_dev *zdev, void *page_addr,
void dma_update_cpu_trans(unsigned long *dma_table, void *page_addr,
			  dma_addr_t dma_addr, int flags)
{
	unsigned long *entry;

	entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr);
	entry = dma_walk_cpu_trans(dma_table, dma_addr);
	if (!entry) {
		WARN_ON_ONCE(1);
		return;
@@ -156,7 +156,8 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
		goto no_refresh;

	for (i = 0; i < nr_pages; i++) {
		dma_update_cpu_trans(zdev, page_addr, dma_addr, flags);
		dma_update_cpu_trans(zdev->dma_table, page_addr, dma_addr,
				     flags);
		page_addr += PAGE_SIZE;
		dma_addr += PAGE_SIZE;
	}
@@ -181,7 +182,7 @@ no_refresh:
	return rc;
}

static void dma_free_seg_table(unsigned long entry)
void dma_free_seg_table(unsigned long entry)
{
	unsigned long *sto = get_rt_sto(entry);
	int sx;
@@ -193,21 +194,18 @@ static void dma_free_seg_table(unsigned long entry)
	dma_free_cpu_table(sto);
}

static void dma_cleanup_tables(struct zpci_dev *zdev)
void dma_cleanup_tables(unsigned long *table)
{
	unsigned long *table;
	int rtx;

	if (!zdev || !zdev->dma_table)
	if (!table)
		return;

	table = zdev->dma_table;
	for (rtx = 0; rtx < ZPCI_TABLE_ENTRIES; rtx++)
		if (reg_entry_isvalid(table[rtx]))
			dma_free_seg_table(table[rtx]);

	dma_free_cpu_table(table);
	zdev->dma_table = NULL;
}

static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
@@ -416,6 +414,13 @@ int zpci_dma_init_device(struct zpci_dev *zdev)
{
	int rc;

	/*
	 * At this point, if the device is part of an IOMMU domain, this would
	 * be a strong hint towards a bug in the IOMMU API (common) code and/or
	 * simultaneous access via IOMMU and DMA API. So let's issue a warning.
	 */
	WARN_ON(zdev->s390_domain);

	spin_lock_init(&zdev->iommu_bitmap_lock);
	spin_lock_init(&zdev->dma_table_lock);

@@ -450,8 +455,16 @@ out_clean:

void zpci_dma_exit_device(struct zpci_dev *zdev)
{
	/*
	 * At this point, if the device is part of an IOMMU domain, this would
	 * be a strong hint towards a bug in the IOMMU API (common) code and/or
	 * simultaneous access via IOMMU and DMA API. So let's issue a warning.
	 */
	WARN_ON(zdev->s390_domain);

	zpci_unregister_ioat(zdev, 0);
	dma_cleanup_tables(zdev);
	dma_cleanup_tables(zdev->dma_table);
	zdev->dma_table = NULL;
	vfree(zdev->iommu_bitmap);
	zdev->iommu_bitmap = NULL;
	zdev->next_bit = 0;
Loading