Re: [Qemu-devel] [PATCH v5 03/10] pci: Convert msix_init() to Error and fix callers to check it
On 11/04/2016 05:01 AM, Cao jin wrote: On 11/03/2016 07:38 PM, Marcel Apfelbaum wrote: On 11/03/2016 06:06 AM, Cao jin wrote: [...] diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 52a4123..fada834 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2360,9 +2360,12 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp) if (megasas_use_msix(s) && msix_init(dev, 15, >mmio_io, b->mmio_bar, 0x2000, - >mmio_io, b->mmio_bar, 0x3800, 0x68)) { + >mmio_io, b->mmio_bar, 0x3800, 0x68, )) { +/*TODO: check msix_init's error, and should fail on msix=on */ Why this "TODO", can't we do something similar to other changes already done in this patch? The 1st version of this series handles the error in this patch. look at the comments: http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg03192.html *First convert msix_init() without changing behavior, by having every caller of msix_init() immediately pass the error received to error_report_err(). Then clean up the callers one after the other.* So later, this patch looks like what it is now. I feel it also make this patch thinner, easier to review. I thought it can be solved in the same way as in the other places, however I am OK with it. +error_report_err(err); s->msix = ON_OFF_AUTO_OFF; } + if (pci_is_express(dev)) { pcie_endpoint_cap_init(dev, 0xa0); } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index d7dbe0e..6fbd30f 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1432,6 +1432,7 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp) static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) { int ret; +Error *err = NULL; vdev->msix->pending = g_malloc0(BITS_TO_LONGS(vdev->msix->entries) * sizeof(unsigned long)); @@ -1439,7 +1440,8 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) vdev->bars[vdev->msix->table_bar].region.mem, vdev->msix->table_bar, vdev->msix->table_offset, vdev->bars[vdev->msix->pba_bar].region.mem, -vdev->msix->pba_bar, vdev->msix->pba_offset, pos); +vdev->msix->pba_bar, vdev->msix->pba_offset, pos, +); Do we pass the err pointer to msix_init, but we don't do anything with it? Also since we do have an *errp in the function already, I suggest renaming err -> local_err or something. (only if the series needs a re-spin) yes, it maybe need a re-spin, thanks if (ret < 0) { if (ret == -ENOTSUP) { return 0; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 06831de..5acce38 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1693,13 +1693,12 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (proxy->nvectors) { int err = msix_init_exclusive_bar(>pci_dev, proxy->nvectors, - proxy->msix_bar_idx); + proxy->msix_bar_idx, errp); +/* Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error. */ +assert(!err || err == -ENOTSUP); if (err) { -/* Notice when a system that supports MSIx can't initialize it. */ -if (err != -ENOTSUP) { -error_report("unable to init msix vectors to %" PRIu32, - proxy->nvectors); -} +error_report_err(*errp); Why do we report the error here and we don't let the propagation mechanism do its thing? We can prep-end the current message, I think. The original behaviour won't fail on msix init failure, so, report & free the Error keep the behaviour same as before, propagation will results in failing to create virtio device. Got it Thanks, Marcel Other than a few questions, the patch looks good to me. Thanks! Marcel
Re: [Qemu-devel] [PATCH v5 03/10] pci: Convert msix_init() to Error and fix callers to check it
On 11/03/2016 07:38 PM, Marcel Apfelbaum wrote: On 11/03/2016 06:06 AM, Cao jin wrote: [...] diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 52a4123..fada834 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2360,9 +2360,12 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp) if (megasas_use_msix(s) && msix_init(dev, 15, >mmio_io, b->mmio_bar, 0x2000, - >mmio_io, b->mmio_bar, 0x3800, 0x68)) { + >mmio_io, b->mmio_bar, 0x3800, 0x68, )) { +/*TODO: check msix_init's error, and should fail on msix=on */ Why this "TODO", can't we do something similar to other changes already done in this patch? The 1st version of this series handles the error in this patch. look at the comments: http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg03192.html *First convert msix_init() without changing behavior, by having every caller of msix_init() immediately pass the error received to error_report_err(). Then clean up the callers one after the other.* So later, this patch looks like what it is now. I feel it also make this patch thinner, easier to review. +error_report_err(err); s->msix = ON_OFF_AUTO_OFF; } + if (pci_is_express(dev)) { pcie_endpoint_cap_init(dev, 0xa0); } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index d7dbe0e..6fbd30f 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1432,6 +1432,7 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp) static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) { int ret; +Error *err = NULL; vdev->msix->pending = g_malloc0(BITS_TO_LONGS(vdev->msix->entries) * sizeof(unsigned long)); @@ -1439,7 +1440,8 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) vdev->bars[vdev->msix->table_bar].region.mem, vdev->msix->table_bar, vdev->msix->table_offset, vdev->bars[vdev->msix->pba_bar].region.mem, -vdev->msix->pba_bar, vdev->msix->pba_offset, pos); +vdev->msix->pba_bar, vdev->msix->pba_offset, pos, +); Do we pass the err pointer to msix_init, but we don't do anything with it? Also since we do have an *errp in the function already, I suggest renaming err -> local_err or something. (only if the series needs a re-spin) yes, it maybe need a re-spin, thanks if (ret < 0) { if (ret == -ENOTSUP) { return 0; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 06831de..5acce38 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1693,13 +1693,12 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (proxy->nvectors) { int err = msix_init_exclusive_bar(>pci_dev, proxy->nvectors, - proxy->msix_bar_idx); + proxy->msix_bar_idx, errp); +/* Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error. */ +assert(!err || err == -ENOTSUP); if (err) { -/* Notice when a system that supports MSIx can't initialize it. */ -if (err != -ENOTSUP) { -error_report("unable to init msix vectors to %" PRIu32, - proxy->nvectors); -} +error_report_err(*errp); Why do we report the error here and we don't let the propagation mechanism do its thing? We can prep-end the current message, I think. The original behaviour won't fail on msix init failure, so, report & free the Error keep the behaviour same as before, propagation will results in failing to create virtio device. Other than a few questions, the patch looks good to me. Thanks! Marcel -- Yours Sincerely, Cao jin
Re: [Qemu-devel] [PATCH v5 03/10] pci: Convert msix_init() to Error and fix callers to check it
On 11/03/2016 06:06 AM, Cao jin wrote: msix_init() reports errors with error_report(), which is wrong when it's used in realize(). The same issue was fixed for msi_init() in commit 1108b2f. For some devices(like e1000e, vmxnet3) who won't fail because of msix_init's failure, suppress the error report by passing NULL error object. Bonus: add comment for msix_init. CC: Jiri PirkoCC: Gerd Hoffmann CC: Dmitry Fleytman CC: Jason Wang CC: Michael S. Tsirkin CC: Hannes Reinecke CC: Paolo Bonzini CC: Alex Williamson CC: Markus Armbruster CC: Marcel Apfelbaum Reviewed-by: Markus Armbruster Signed-off-by: Cao jin --- hw/block/nvme.c| 5 - hw/misc/ivshmem.c | 8 hw/net/e1000e.c| 6 +- hw/net/rocker/rocker.c | 7 ++- hw/net/vmxnet3.c | 8 ++-- hw/pci/msix.c | 34 +- hw/scsi/megasas.c | 5 - hw/usb/hcd-xhci.c | 13 - hw/vfio/pci.c | 4 +++- hw/virtio/virtio-pci.c | 11 +-- include/hw/pci/msix.h | 5 +++-- 11 files changed, 77 insertions(+), 29 deletions(-) [...] diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 52a4123..fada834 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2360,9 +2360,12 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp) if (megasas_use_msix(s) && msix_init(dev, 15, >mmio_io, b->mmio_bar, 0x2000, - >mmio_io, b->mmio_bar, 0x3800, 0x68)) { + >mmio_io, b->mmio_bar, 0x3800, 0x68, )) { +/*TODO: check msix_init's error, and should fail on msix=on */ Why this "TODO", can't we do something similar to other changes already done in this patch? +error_report_err(err); s->msix = ON_OFF_AUTO_OFF; } + if (pci_is_express(dev)) { pcie_endpoint_cap_init(dev, 0xa0); } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index eb1dca5..05dc944 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3703,11 +3703,14 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) } if (xhci->msix != ON_OFF_AUTO_OFF) { -/* TODO check for errors */ -msix_init(dev, xhci->numintrs, - >mem, 0, OFF_MSIX_TABLE, - >mem, 0, OFF_MSIX_PBA, - 0x90); +/* TODO check for errors, and should fail when msix=on */ +ret = msix_init(dev, xhci->numintrs, +>mem, 0, OFF_MSIX_TABLE, +>mem, 0, OFF_MSIX_PBA, +0x90, ); +if (ret) { +error_report_err(err); +} } } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index d7dbe0e..6fbd30f 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1432,6 +1432,7 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp) static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) { int ret; +Error *err = NULL; vdev->msix->pending = g_malloc0(BITS_TO_LONGS(vdev->msix->entries) * sizeof(unsigned long)); @@ -1439,7 +1440,8 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) vdev->bars[vdev->msix->table_bar].region.mem, vdev->msix->table_bar, vdev->msix->table_offset, vdev->bars[vdev->msix->pba_bar].region.mem, -vdev->msix->pba_bar, vdev->msix->pba_offset, pos); +vdev->msix->pba_bar, vdev->msix->pba_offset, pos, +); Do we pass the err pointer to msix_init, but we don't do anything with it? Also since we do have an *errp in the function already, I suggest renaming err -> local_err or something. (only if the series needs a re-spin) if (ret < 0) { if (ret == -ENOTSUP) { return 0; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 06831de..5acce38 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1693,13 +1693,12 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (proxy->nvectors) { int err = msix_init_exclusive_bar(>pci_dev, proxy->nvectors, - proxy->msix_bar_idx); + proxy->msix_bar_idx, errp); +/* Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error. */ +assert(!err || err == -ENOTSUP); if (err) { -/* Notice when a system that supports MSIx can't initialize it. */ -if (err != -ENOTSUP) { -error_report("unable to init msix vectors to %" PRIu32, -
[Qemu-devel] [PATCH v5 03/10] pci: Convert msix_init() to Error and fix callers to check it
msix_init() reports errors with error_report(), which is wrong when it's used in realize(). The same issue was fixed for msi_init() in commit 1108b2f. For some devices(like e1000e, vmxnet3) who won't fail because of msix_init's failure, suppress the error report by passing NULL error object. Bonus: add comment for msix_init. CC: Jiri PirkoCC: Gerd Hoffmann CC: Dmitry Fleytman CC: Jason Wang CC: Michael S. Tsirkin CC: Hannes Reinecke CC: Paolo Bonzini CC: Alex Williamson CC: Markus Armbruster CC: Marcel Apfelbaum Reviewed-by: Markus Armbruster Signed-off-by: Cao jin --- hw/block/nvme.c| 5 - hw/misc/ivshmem.c | 8 hw/net/e1000e.c| 6 +- hw/net/rocker/rocker.c | 7 ++- hw/net/vmxnet3.c | 8 ++-- hw/pci/msix.c | 34 +- hw/scsi/megasas.c | 5 - hw/usb/hcd-xhci.c | 13 - hw/vfio/pci.c | 4 +++- hw/virtio/virtio-pci.c | 11 +-- include/hw/pci/msix.h | 5 +++-- 11 files changed, 77 insertions(+), 29 deletions(-) diff --git a/hw/block/nvme.c b/hw/block/nvme.c index d479fd2..2d703c8 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -831,6 +831,7 @@ static int nvme_init(PCIDevice *pci_dev) { NvmeCtrl *n = NVME(pci_dev); NvmeIdCtrl *id = >id_ctrl; +Error *err = NULL; int i; int64_t bs_size; @@ -872,7 +873,9 @@ static int nvme_init(PCIDevice *pci_dev) pci_register_bar(>parent_obj, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, >iomem); -msix_init_exclusive_bar(>parent_obj, n->num_queues, 4); +if (msix_init_exclusive_bar(>parent_obj, n->num_queues, 4, )) { +error_report_err(err); +} id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID)); id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID)); diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 230e51b..ca6f804 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -749,13 +749,13 @@ static void ivshmem_reset(DeviceState *d) } } -static int ivshmem_setup_interrupts(IVShmemState *s) +static int ivshmem_setup_interrupts(IVShmemState *s, Error **errp) { /* allocate QEMU callback data for receiving interrupts */ s->msi_vectors = g_malloc0(s->vectors * sizeof(MSIVector)); if (ivshmem_has_feature(s, IVSHMEM_MSI)) { -if (msix_init_exclusive_bar(PCI_DEVICE(s), s->vectors, 1)) { +if (msix_init_exclusive_bar(PCI_DEVICE(s), s->vectors, 1, errp)) { return -1; } @@ -897,8 +897,8 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp) qemu_chr_fe_set_handlers(>server_chr, ivshmem_can_receive, ivshmem_read, NULL, s, NULL, true); -if (ivshmem_setup_interrupts(s) < 0) { -error_setg(errp, "failed to initialize interrupts"); +if (ivshmem_setup_interrupts(s, errp) < 0) { +error_prepend(errp, "Failed to initialize interrupts: "); return; } } diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 4994e1c..74cbbef 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -292,7 +292,11 @@ e1000e_init_msix(E1000EState *s) E1000E_MSIX_IDX, E1000E_MSIX_TABLE, >msix, E1000E_MSIX_IDX, E1000E_MSIX_PBA, -0xA0); +0xA0, NULL); + +/* Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error. Fall back to INTx silently on -ENOTSUP */ +assert(!res || res == -ENOTSUP); if (res < 0) { trace_e1000e_msix_init_fail(res); diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index e9d215a..8f829f2 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -1256,14 +1256,19 @@ static int rocker_msix_init(Rocker *r) { PCIDevice *dev = PCI_DEVICE(r); int err; +Error *local_err = NULL; err = msix_init(dev, ROCKER_MSIX_VEC_COUNT(r->fp_ports), >msix_bar, ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_TABLE_OFFSET, >msix_bar, ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET, -0); +0, _err); +/* Any error other than -ENOTSUP(board's MSI support is broken) + * is a programming error. */ +assert(!err || err == -ENOTSUP); if (err) { +error_report_err(local_err); return err; } diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 92f6af9..a433cc0 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2191,10 +2191,14 @@