iommu/s390: handle IOAT registration based on domain
JIRA: https://issues.redhat.com/browse/RHEL-11431 commit 0ed5967a0a63552e5ca0f2382ce362f84e83801c Author: Matthew Rosato <mjrosato@linux.ibm.com> Date: Wed Feb 12 16:34:17 2025 -0500 iommu/s390: handle IOAT registration based on domain At this point, the dma_table is really a property of the s390-iommu domain. Rather than checking its contents elsewhere in the codebase, move the code that registers the table with firmware into s390-iommu and make a decision what to register with firmware based upon the type of domain in use for the device in question. Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/r/20250212213418.182902-4-mjrosato@linux.ibm.com Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Christoph Schlameuss <cschlame@redhat.com>
This commit is contained in:
parent
93a7b64dd0
commit
57e06c3f48
|
@ -217,6 +217,7 @@ extern struct airq_iv *zpci_aif_sbv;
|
|||
struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state);
|
||||
int zpci_add_device(struct zpci_dev *zdev);
|
||||
int zpci_enable_device(struct zpci_dev *);
|
||||
int zpci_reenable_device(struct zpci_dev *zdev);
|
||||
int zpci_disable_device(struct zpci_dev *);
|
||||
int zpci_scan_configured_device(struct zpci_dev *zdev, u32 fh);
|
||||
int zpci_deconfigure_device(struct zpci_dev *zdev);
|
||||
|
@ -245,6 +246,7 @@ void update_uid_checking(bool new);
|
|||
/* IOMMU Interface */
|
||||
int zpci_init_iommu(struct zpci_dev *zdev);
|
||||
void zpci_destroy_iommu(struct zpci_dev *zdev);
|
||||
int zpci_iommu_register_ioat(struct zpci_dev *zdev, u8 *status);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline bool zpci_use_mio(struct zpci_dev *zdev)
|
||||
|
|
|
@ -433,7 +433,6 @@ static void kvm_s390_pci_dev_release(struct zpci_dev *zdev)
|
|||
static int kvm_s390_pci_register_kvm(void *opaque, struct kvm *kvm)
|
||||
{
|
||||
struct zpci_dev *zdev = opaque;
|
||||
u8 status;
|
||||
int rc;
|
||||
|
||||
if (!zdev)
|
||||
|
@ -480,13 +479,7 @@ static int kvm_s390_pci_register_kvm(void *opaque, struct kvm *kvm)
|
|||
*/
|
||||
zdev->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa);
|
||||
|
||||
rc = zpci_enable_device(zdev);
|
||||
if (rc)
|
||||
goto clear_gisa;
|
||||
|
||||
/* Re-register the IOMMU that was already created */
|
||||
rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
|
||||
virt_to_phys(zdev->dma_table), &status);
|
||||
rc = zpci_reenable_device(zdev);
|
||||
if (rc)
|
||||
goto clear_gisa;
|
||||
|
||||
|
@ -516,7 +509,6 @@ static void kvm_s390_pci_unregister_kvm(void *opaque)
|
|||
{
|
||||
struct zpci_dev *zdev = opaque;
|
||||
struct kvm *kvm;
|
||||
u8 status;
|
||||
|
||||
if (!zdev)
|
||||
return;
|
||||
|
@ -550,12 +542,7 @@ static void kvm_s390_pci_unregister_kvm(void *opaque)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (zpci_enable_device(zdev))
|
||||
goto out;
|
||||
|
||||
/* Re-register the IOMMU that was already created */
|
||||
zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
|
||||
virt_to_phys(zdev->dma_table), &status);
|
||||
zpci_reenable_device(zdev);
|
||||
|
||||
out:
|
||||
spin_lock(&kvm->arch.kzdev_list_lock);
|
||||
|
|
|
@ -134,14 +134,13 @@ int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
|
|||
struct zpci_fib fib = {0};
|
||||
u8 cc;
|
||||
|
||||
WARN_ON_ONCE(iota & 0x3fff);
|
||||
fib.pba = base;
|
||||
/* Work around off by one in ISM virt device */
|
||||
if (zdev->pft == PCI_FUNC_TYPE_ISM && limit > base)
|
||||
fib.pal = limit + (1 << 12);
|
||||
else
|
||||
fib.pal = limit;
|
||||
fib.iota = iota | ZPCI_IOTA_RTTO_FLAG;
|
||||
fib.iota = iota;
|
||||
fib.gd = zdev->gisa;
|
||||
cc = zpci_mod_fc(req, &fib, status);
|
||||
if (cc)
|
||||
|
@ -700,6 +699,23 @@ int zpci_enable_device(struct zpci_dev *zdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(zpci_enable_device);
|
||||
|
||||
int zpci_reenable_device(struct zpci_dev *zdev)
|
||||
{
|
||||
u8 status;
|
||||
int rc;
|
||||
|
||||
rc = zpci_enable_device(zdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = zpci_iommu_register_ioat(zdev, &status);
|
||||
if (rc)
|
||||
zpci_disable_device(zdev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zpci_reenable_device);
|
||||
|
||||
int zpci_disable_device(struct zpci_dev *zdev)
|
||||
{
|
||||
u32 fh = zdev->fh;
|
||||
|
@ -749,7 +765,6 @@ EXPORT_SYMBOL_GPL(zpci_disable_device);
|
|||
*/
|
||||
int zpci_hot_reset_device(struct zpci_dev *zdev)
|
||||
{
|
||||
u8 status;
|
||||
int rc;
|
||||
|
||||
lockdep_assert_held(&zdev->state_lock);
|
||||
|
@ -768,19 +783,9 @@ int zpci_hot_reset_device(struct zpci_dev *zdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = zpci_enable_device(zdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = zpci_reenable_device(zdev);
|
||||
|
||||
if (zdev->dma_table)
|
||||
rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
|
||||
virt_to_phys(zdev->dma_table), &status);
|
||||
if (rc) {
|
||||
zpci_disable_device(zdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,7 +52,6 @@ static DEVICE_ATTR_RO(mio_enabled);
|
|||
|
||||
static int _do_recover(struct pci_dev *pdev, struct zpci_dev *zdev)
|
||||
{
|
||||
u8 status;
|
||||
int ret;
|
||||
|
||||
pci_stop_and_remove_bus_device(pdev);
|
||||
|
@ -70,16 +69,8 @@ static int _do_recover(struct pci_dev *pdev, struct zpci_dev *zdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = zpci_enable_device(zdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = zpci_reenable_device(zdev);
|
||||
|
||||
if (zdev->dma_table) {
|
||||
ret = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
|
||||
virt_to_phys(zdev->dma_table), &status);
|
||||
if (ret)
|
||||
zpci_disable_device(zdev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -381,6 +381,46 @@ static void zdev_s390_domain_update(struct zpci_dev *zdev,
|
|||
spin_unlock_irqrestore(&zdev->dom_lock, flags);
|
||||
}
|
||||
|
||||
static int s390_iommu_domain_reg_ioat(struct zpci_dev *zdev,
|
||||
struct iommu_domain *domain, u8 *status)
|
||||
{
|
||||
struct s390_domain *s390_domain;
|
||||
int rc = 0;
|
||||
u64 iota;
|
||||
|
||||
switch (domain->type) {
|
||||
case IOMMU_DOMAIN_IDENTITY:
|
||||
rc = zpci_register_ioat(zdev, 0, zdev->start_dma,
|
||||
zdev->end_dma, 0, status);
|
||||
break;
|
||||
case IOMMU_DOMAIN_BLOCKED:
|
||||
/* Nothing to do in this case */
|
||||
break;
|
||||
default:
|
||||
s390_domain = to_s390_domain(domain);
|
||||
iota = virt_to_phys(s390_domain->dma_table) |
|
||||
ZPCI_IOTA_RTTO_FLAG;
|
||||
rc = zpci_register_ioat(zdev, 0, zdev->start_dma,
|
||||
zdev->end_dma, iota, status);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zpci_iommu_register_ioat(struct zpci_dev *zdev, u8 *status)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
spin_lock_irqsave(&zdev->dom_lock, flags);
|
||||
|
||||
rc = s390_iommu_domain_reg_ioat(zdev, zdev->s390_domain, status);
|
||||
|
||||
spin_unlock_irqrestore(&zdev->dom_lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int blocking_domain_attach_device(struct iommu_domain *domain,
|
||||
struct device *dev)
|
||||
{
|
||||
|
@ -422,8 +462,7 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
|
|||
blocking_domain_attach_device(&blocking_domain, dev);
|
||||
|
||||
/* If we fail now DMA remains blocked via blocking domain */
|
||||
cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
|
||||
virt_to_phys(s390_domain->dma_table), &status);
|
||||
cc = s390_iommu_domain_reg_ioat(zdev, domain, &status);
|
||||
if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL)
|
||||
return -EIO;
|
||||
zdev->dma_table = s390_domain->dma_table;
|
||||
|
|
Loading…
Reference in New Issue