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: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
ef954844c7
commit
f42c223514
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/iommu.h>
|
||||||
#include <asm-generic/pci.h>
|
#include <asm-generic/pci.h>
|
||||||
#include <asm/pci_clp.h>
|
#include <asm/pci_clp.h>
|
||||||
#include <asm/pci_debug.h>
|
#include <asm/pci_debug.h>
|
||||||
|
@ -122,6 +123,8 @@ struct zpci_dev {
|
||||||
unsigned long iommu_pages;
|
unsigned long iommu_pages;
|
||||||
unsigned int next_bit;
|
unsigned int next_bit;
|
||||||
|
|
||||||
|
struct iommu_device iommu_dev; /* IOMMU core handle */
|
||||||
|
|
||||||
char res_name[16];
|
char res_name[16];
|
||||||
struct zpci_bar_struct bars[PCI_BAR_COUNT];
|
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_disable_fh(struct zpci_dev *);
|
||||||
int clp_get_state(u32 fid, enum zpci_state *state);
|
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
|
#ifdef CONFIG_PCI
|
||||||
/* Error handling and recovery */
|
/* Error handling and recovery */
|
||||||
void zpci_event_error(void *);
|
void zpci_event_error(void *);
|
||||||
|
|
|
@ -776,6 +776,7 @@ void pcibios_remove_bus(struct pci_bus *bus)
|
||||||
|
|
||||||
zpci_exit_slot(zdev);
|
zpci_exit_slot(zdev);
|
||||||
zpci_cleanup_bus_resources(zdev);
|
zpci_cleanup_bus_resources(zdev);
|
||||||
|
zpci_destroy_iommu(zdev);
|
||||||
zpci_free_domain(zdev);
|
zpci_free_domain(zdev);
|
||||||
|
|
||||||
spin_lock(&zpci_list_lock);
|
spin_lock(&zpci_list_lock);
|
||||||
|
@ -848,11 +849,15 @@ int zpci_create_device(struct zpci_dev *zdev)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
rc = zpci_init_iommu(zdev);
|
||||||
|
if (rc)
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
mutex_init(&zdev->lock);
|
mutex_init(&zdev->lock);
|
||||||
if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
|
if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
|
||||||
rc = zpci_enable_device(zdev);
|
rc = zpci_enable_device(zdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free;
|
goto out_destroy_iommu;
|
||||||
}
|
}
|
||||||
rc = zpci_scan_bus(zdev);
|
rc = zpci_scan_bus(zdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -869,6 +874,8 @@ int zpci_create_device(struct zpci_dev *zdev)
|
||||||
out_disable:
|
out_disable:
|
||||||
if (zdev->state == ZPCI_FN_STATE_ONLINE)
|
if (zdev->state == ZPCI_FN_STATE_ONLINE)
|
||||||
zpci_disable_device(zdev);
|
zpci_disable_device(zdev);
|
||||||
|
out_destroy_iommu:
|
||||||
|
zpci_destroy_iommu(zdev);
|
||||||
out_free:
|
out_free:
|
||||||
zpci_free_domain(zdev);
|
zpci_free_domain(zdev);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
#define S390_IOMMU_PGSIZES (~0xFFFUL)
|
#define S390_IOMMU_PGSIZES (~0xFFFUL)
|
||||||
|
|
||||||
|
static struct iommu_ops s390_iommu_ops;
|
||||||
|
|
||||||
struct s390_domain {
|
struct s390_domain {
|
||||||
struct iommu_domain domain;
|
struct iommu_domain domain;
|
||||||
struct list_head devices;
|
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)
|
static int s390_iommu_add_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct iommu_group *group = iommu_group_get_for_dev(dev);
|
struct iommu_group *group = iommu_group_get_for_dev(dev);
|
||||||
|
struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
|
||||||
|
|
||||||
if (IS_ERR(group))
|
if (IS_ERR(group))
|
||||||
return PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
|
|
||||||
iommu_group_put(group);
|
iommu_group_put(group);
|
||||||
|
iommu_device_link(&zdev->iommu_dev, dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -197,6 +201,7 @@ static void s390_iommu_remove_device(struct device *dev)
|
||||||
s390_iommu_detach_device(domain, dev);
|
s390_iommu_detach_device(domain, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iommu_device_unlink(&zdev->iommu_dev, dev);
|
||||||
iommu_group_remove_device(dev);
|
iommu_group_remove_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,6 +332,36 @@ static size_t s390_iommu_unmap(struct iommu_domain *domain,
|
||||||
return size;
|
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 = {
|
static struct iommu_ops s390_iommu_ops = {
|
||||||
.capable = s390_iommu_capable,
|
.capable = s390_iommu_capable,
|
||||||
.domain_alloc = s390_domain_alloc,
|
.domain_alloc = s390_domain_alloc,
|
||||||
|
|
Loading…
Reference in New Issue