Commit f42c2235 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/s390: Add support for iommu_device handling



Add support for the iommu_device_register interface to make
the s390 hardware iommus visible to the iommu core and in
sysfs.

Acked-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent ef954844
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/iommu.h>
#include <asm-generic/pci.h>
#include <asm/pci_clp.h>
#include <asm/pci_debug.h>
@@ -122,6 +123,8 @@ struct zpci_dev {
	unsigned long	iommu_pages;
	unsigned int	next_bit;

	struct iommu_device iommu_dev;  /* IOMMU core handle */

	char res_name[16];
	struct zpci_bar_struct bars[PCI_BAR_COUNT];

@@ -174,6 +177,10 @@ int clp_enable_fh(struct zpci_dev *, u8);
int clp_disable_fh(struct zpci_dev *);
int clp_get_state(u32 fid, enum zpci_state *state);

/* IOMMU Interface */
int zpci_init_iommu(struct zpci_dev *zdev);
void zpci_destroy_iommu(struct zpci_dev *zdev);

#ifdef CONFIG_PCI
/* Error handling and recovery */
void zpci_event_error(void *);
+8 −1
Original line number Diff line number Diff line
@@ -776,6 +776,7 @@ void pcibios_remove_bus(struct pci_bus *bus)

	zpci_exit_slot(zdev);
	zpci_cleanup_bus_resources(zdev);
	zpci_destroy_iommu(zdev);
	zpci_free_domain(zdev);

	spin_lock(&zpci_list_lock);
@@ -848,11 +849,15 @@ int zpci_create_device(struct zpci_dev *zdev)
	if (rc)
		goto out;

	rc = zpci_init_iommu(zdev);
	if (rc)
		goto out_free;

	mutex_init(&zdev->lock);
	if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
		rc = zpci_enable_device(zdev);
		if (rc)
			goto out_free;
			goto out_destroy_iommu;
	}
	rc = zpci_scan_bus(zdev);
	if (rc)
@@ -869,6 +874,8 @@ int zpci_create_device(struct zpci_dev *zdev)
out_disable:
	if (zdev->state == ZPCI_FN_STATE_ONLINE)
		zpci_disable_device(zdev);
out_destroy_iommu:
	zpci_destroy_iommu(zdev);
out_free:
	zpci_free_domain(zdev);
out:
+35 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
 */
#define S390_IOMMU_PGSIZES	(~0xFFFUL)

static struct iommu_ops s390_iommu_ops;

struct s390_domain {
	struct iommu_domain	domain;
	struct list_head	devices;
@@ -166,11 +168,13 @@ static void s390_iommu_detach_device(struct iommu_domain *domain,
static int s390_iommu_add_device(struct device *dev)
{
	struct iommu_group *group = iommu_group_get_for_dev(dev);
	struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;

	if (IS_ERR(group))
		return PTR_ERR(group);

	iommu_group_put(group);
	iommu_device_link(&zdev->iommu_dev, dev);

	return 0;
}
@@ -197,6 +201,7 @@ static void s390_iommu_remove_device(struct device *dev)
			s390_iommu_detach_device(domain, dev);
	}

	iommu_device_unlink(&zdev->iommu_dev, dev);
	iommu_group_remove_device(dev);
}

@@ -327,6 +332,36 @@ static size_t s390_iommu_unmap(struct iommu_domain *domain,
	return size;
}

int zpci_init_iommu(struct zpci_dev *zdev)
{
	int rc = 0;

	rc = iommu_device_sysfs_add(&zdev->iommu_dev, NULL, NULL,
				    "s390-iommu.%08x", zdev->fid);
	if (rc)
		goto out_err;

	iommu_device_set_ops(&zdev->iommu_dev, &s390_iommu_ops);

	rc = iommu_device_register(&zdev->iommu_dev);
	if (rc)
		goto out_sysfs;

	return 0;

out_sysfs:
	iommu_device_sysfs_remove(&zdev->iommu_dev);

out_err:
	return rc;
}

void zpci_destroy_iommu(struct zpci_dev *zdev)
{
	iommu_device_unregister(&zdev->iommu_dev);
	iommu_device_sysfs_remove(&zdev->iommu_dev);
}

static struct iommu_ops s390_iommu_ops = {
	.capable = s390_iommu_capable,
	.domain_alloc = s390_domain_alloc,