aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x/s390-pci-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/s390-pci-bus.c')
-rw-r--r--hw/s390x/s390-pci-bus.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 918b58543e..a77c10ce9e 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -15,6 +15,7 @@
#include "qemu-common.h"
#include "cpu.h"
#include "s390-pci-bus.h"
+#include "s390-pci-inst.h"
#include <hw/pci/pci_bus.h>
#include <hw/pci/msi.h>
#include <qemu/error-report.h>
@@ -106,25 +107,61 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
return NULL;
}
-void s390_pci_sclp_configure(int configure, SCCB *sccb)
+void s390_pci_sclp_configure(SCCB *sccb)
{
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
uint16_t rc;
+ if (be16_to_cpu(sccb->h.length) < 16) {
+ rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
+ goto out;
+ }
+
if (pbdev) {
- if ((configure == 1 && pbdev->configured == true) ||
- (configure == 0 && pbdev->configured == false)) {
+ if (pbdev->configured) {
rc = SCLP_RC_NO_ACTION_REQUIRED;
} else {
- pbdev->configured = !pbdev->configured;
+ pbdev->configured = true;
rc = SCLP_RC_NORMAL_COMPLETION;
}
} else {
- DPRINTF("sclp config %d no dev found\n", configure);
+ DPRINTF("sclp config no dev found\n");
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
}
+out:
+ psccb->header.response_code = cpu_to_be16(rc);
+}
+
+void s390_pci_sclp_deconfigure(SCCB *sccb)
+{
+ PciCfgSccb *psccb = (PciCfgSccb *)sccb;
+ S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
+ uint16_t rc;
+
+ if (be16_to_cpu(sccb->h.length) < 16) {
+ rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
+ goto out;
+ }
+ if (pbdev) {
+ if (!pbdev->configured) {
+ rc = SCLP_RC_NO_ACTION_REQUIRED;
+ } else {
+ if (pbdev->summary_ind) {
+ pci_dereg_irqs(pbdev);
+ }
+ if (pbdev->iommu_enabled) {
+ pci_dereg_ioat(pbdev);
+ }
+ pbdev->configured = false;
+ rc = SCLP_RC_NORMAL_COMPLETION;
+ }
+ } else {
+ DPRINTF("sclp deconfig no dev found\n");
+ rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
+ }
+out:
psccb->header.response_code = cpu_to_be16(rc);
}
@@ -320,7 +357,8 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
.perm = IOMMU_NONE,
};
- if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) {
+ if (!pbdev->configured || !pbdev->pdev ||
+ !(pbdev->fh & FH_ENABLED) || !pbdev->iommu_enabled) {
return ret;
}
@@ -458,20 +496,21 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable)
+void s390_pci_iommu_enable(S390PCIBusDevice *pbdev)
{
- pbdev->configured = false;
+ uint64_t size = pbdev->pal - pbdev->pba + 1;
- if (enable) {
- uint64_t size = pbdev->pal - pbdev->pba + 1;
- memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr),
- &s390_iommu_ops, "iommu-s390", size);
- memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr);
- } else {
- memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr);
- }
+ memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr),
+ &s390_iommu_ops, "iommu-s390", size);
+ memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr);
+ pbdev->iommu_enabled = true;
+}
- pbdev->configured = true;
+void s390_pci_iommu_disable(S390PCIBusDevice *pbdev)
+{
+ memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr);
+ object_unparent(OBJECT(&pbdev->iommu_mr));
+ pbdev->iommu_enabled = false;
}
static void s390_pcihost_init_as(S390pciState *s)