diff options
Diffstat (limited to 'hw/s390x/s390-pci-bus.c')
-rw-r--r-- | hw/s390x/s390-pci-bus.c | 69 |
1 files changed, 31 insertions, 38 deletions
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 9c1c04e590..63f6248f1d 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -383,7 +383,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, uint64_t pte; uint32_t flags; S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr); - S390pciState *s; IOMMUTLBEntry ret = { .target_as = &address_space_memory, .iova = 0, @@ -405,19 +404,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr); - s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent); - /* s390 does not have an APIC mapped to main storage so we use - * a separate AddressSpace only for msix notifications - */ - if (addr == ZPCI_MSI_ADDR) { - ret.target_as = &s->msix_notify_as; - ret.iova = addr; - ret.translated_addr = addr; - ret.addr_mask = 0xfff; - ret.perm = IOMMU_RW; - return ret; - } - if (addr < pbdev->pba || addr > pbdev->pal) { return ret; } @@ -476,8 +462,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { - S390PCIBusDevice *pbdev; - uint32_t io_int_word; + S390PCIBusDevice *pbdev = opaque; uint32_t idx = data >> ZPCI_MSI_VEC_BITS; uint32_t vec = data & ZPCI_MSI_VEC_MASK; uint64_t ind_bit; @@ -486,7 +471,6 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec); - pbdev = s390_pci_find_dev_by_idx(idx); if (!pbdev) { e |= (vec << ERR_EVENT_MVN_OFFSET); s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e); @@ -504,8 +488,7 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, 0x80 >> ((ind_bit + vec) % 8)); if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, 0x80 >> (sum_bit % 8))) { - io_int_word = (pbdev->isc << 27) | IO_INT_WORD_AI; - s390_io_interrupt(0, 0, 0, io_int_word); + css_adapter_interrupt(pbdev->isc); } } @@ -548,10 +531,6 @@ static void s390_pcihost_init_as(S390pciState *s) s->iommu[i] = iommu; } - - memory_region_init_io(&s->msix_notify_mr, OBJECT(s), - &s390_msi_ctrl_ops, s, "msix-s390", UINT64_MAX); - address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci"); } static int s390_pcihost_init(SysBusDevice *dev) @@ -581,7 +560,7 @@ static int s390_pcihost_init(SysBusDevice *dev) return 0; } -static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) +static int s390_pci_setup_msix(S390PCIBusDevice *pbdev) { uint8_t pos; uint16_t ctrl; @@ -609,6 +588,26 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) return 0; } +static void s390_pci_msix_init(S390PCIBusDevice *pbdev) +{ + char *name; + + name = g_strdup_printf("msix-s390-%04x", pbdev->uid); + + memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev), + &s390_msi_ctrl_ops, pbdev, name, PAGE_SIZE); + memory_region_add_subregion(&pbdev->iommu->mr, ZPCI_MSI_ADDR, + &pbdev->msix_notify_mr); + + g_free(name); +} + +static void s390_pci_msix_free(S390PCIBusDevice *pbdev) +{ + memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr); + object_unparent(OBJECT(&pbdev->msix_notify_mr)); +} + static S390PCIBusDevice *s390_pci_device_new(const char *target) { DeviceState *dev = NULL; @@ -649,6 +648,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, pbdev = s390_pci_device_new(dev->id); if (!pbdev) { error_setg(errp, "create zpci device failed"); + return; } } @@ -661,7 +661,9 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, pbdev->pdev = pdev; pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)]; pbdev->state = ZPCI_FS_STANDBY; - s390_pcihost_setup_msix(pbdev); + + s390_pci_msix_init(pbdev); + s390_pci_setup_msix(pbdev); if (dev->hotplugged) { s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, @@ -717,11 +719,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, break; } } - - if (!pbdev) { - object_unparent(OBJECT(pci_dev)); - return; - } + assert(pbdev != NULL); } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { pbdev = S390_PCI_DEVICE(dev); pci_dev = pbdev->pdev; @@ -752,6 +750,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, pbdev->fh, pbdev->fid); object_unparent(OBJECT(pci_dev)); + s390_pci_msix_free(pbdev); pbdev->pdev = NULL; pbdev->state = ZPCI_FS_RESERVED; out: @@ -808,17 +807,11 @@ static uint32_t s390_pci_generate_fid(Error **errp) { uint32_t fid = 0; - while (fid <= ZPCI_MAX_FID) { + do { if (!s390_pci_find_dev_by_fid(fid)) { return fid; } - - if (fid == ZPCI_MAX_FID) { - break; - } - - fid++; - } + } while (fid++ != ZPCI_MAX_FID); error_setg(errp, "no free fid could be found"); return 0; |