Skip to content

Commit

Permalink
iommu/s390: Add iommu api for s390 pci devices
Browse files Browse the repository at this point in the history
This adds an IOMMU API implementation for s390 PCI devices.

Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Gerald Schaefer authored and Joerg Roedel committed Oct 6, 2015
1 parent 049e6dd commit 8128f23
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 13 deletions.
7 changes: 7 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ menuconfig PCI
bool "PCI support"
select HAVE_DMA_ATTRS
select PCI_MSI
select IOMMU_SUPPORT
help
Enable PCI support.

Expand Down
4 changes: 4 additions & 0 deletions arch/s390/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion arch/s390/include/asm/pci_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
37 changes: 25 additions & 12 deletions arch/s390/pci/pci_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
dma_addr_t dma_addr, int flags)
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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -181,7 +182,7 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
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;
Expand All @@ -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,
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -450,8 +455,16 @@ int zpci_dma_init_device(struct zpci_dev *zdev)

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;
Expand Down
7 changes: 7 additions & 0 deletions drivers/iommu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,11 @@ config ARM_SMMU_V3
Say Y here if your system includes an IOMMU device implementing
the ARM SMMUv3 architecture.

config S390_IOMMU
def_bool y if S390 && PCI
depends on S390 && PCI
select IOMMU_API
help
Support for the IOMMU API for s390 PCI devices.

endif # IOMMU_SUPPORT
1 change: 1 addition & 0 deletions drivers/iommu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o
obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o
obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
obj-$(CONFIG_S390_IOMMU) += s390-iommu.o
Loading

0 comments on commit 8128f23

Please sign in to comment.